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

Conflicts:
	src/core/iomgr/resolve_address_posix.c
	src/core/surface/server.c
pull/1731/head
Craig Tiller 10 years ago
commit a4b89fed1c
  1. 40
      BUILD
  2. 350
      Makefile
  3. 177
      build.json
  4. 25
      gRPC.podspec
  5. 6
      include/grpc++/impl/sync_no_cxx11.h
  6. 4
      include/grpc++/impl/thd_no_cxx11.h
  7. 4
      include/grpc++/server_context.h
  8. 95
      include/grpc/census.h
  9. 63
      src/compiler/objective_c_generator.cc
  10. 9
      src/compiler/objective_c_generator.h
  11. 12
      src/compiler/objective_c_generator_helpers.h
  12. 4
      src/compiler/objective_c_plugin.cc
  13. 71
      src/core/census/README.md
  14. 32
      src/core/census/context.c
  15. 26
      src/core/census/context.h
  16. 24
      src/core/census/grpc_context.c
  17. 12
      src/core/census/grpc_context.h
  18. 29
      src/core/census/initialize.c
  19. 11
      src/core/channel/child_channel.c
  20. 3
      src/core/iomgr/endpoint_pair.h
  21. 17
      src/core/iomgr/endpoint_pair_posix.c
  22. 6
      src/core/iomgr/endpoint_pair_windows.c
  23. 60
      src/core/iomgr/fd_posix.c
  24. 16
      src/core/iomgr/fd_posix.h
  25. 125
      src/core/iomgr/iomgr.c
  26. 37
      src/core/iomgr/iomgr.h
  27. 14
      src/core/iomgr/iomgr_internal.h
  28. 7
      src/core/iomgr/pollset_posix.c
  29. 10
      src/core/iomgr/pollset_windows.c
  30. 14
      src/core/iomgr/resolve_address_posix.c
  31. 8
      src/core/iomgr/resolve_address_windows.c
  32. 17
      src/core/iomgr/socket_windows.c
  33. 9
      src/core/iomgr/socket_windows.h
  34. 22
      src/core/iomgr/tcp_client_posix.c
  35. 2
      src/core/iomgr/tcp_client_windows.c
  36. 7
      src/core/iomgr/tcp_posix.c
  37. 23
      src/core/iomgr/tcp_server_posix.c
  38. 5
      src/core/iomgr/tcp_server_windows.c
  39. 12
      src/core/security/credentials.c
  40. 43
      src/core/surface/call.c
  41. 5
      src/core/surface/channel.c
  42. 3
      src/core/surface/channel_create.c
  43. 6
      src/core/surface/init.c
  44. 3
      src/core/surface/secure_channel_create.c
  45. 46
      src/core/surface/server.c
  46. 6
      src/core/transport/chttp2/gen_hpack_tables.c
  47. 5
      src/cpp/server/thread_pool.cc
  48. 2
      src/cpp/server/thread_pool.h
  49. 4
      src/csharp/.nuget/packages.config
  50. 6
      src/csharp/Grpc.Auth/Grpc.Auth.nuspec
  51. 6
      src/csharp/Grpc.Core/Grpc.Core.nuspec
  52. 4
      src/csharp/Grpc.Tools.nuspec
  53. 6
      src/csharp/Grpc.nuspec
  54. 62
      src/csharp/Grpc.sln
  55. 6
      src/csharp/buildall.bat
  56. 86
      src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
  57. 8
      src/objective-c/examples/Sample/Podfile
  58. 185
      src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
  59. 3
      src/objective-c/examples/Sample/Sample/AppDelegate.h
  60. 8
      src/objective-c/examples/Sample/Sample/AppDelegate.m
  61. 41
      src/objective-c/examples/Sample/Sample/Base.lproj/LaunchScreen.xib
  62. 38
      src/objective-c/examples/Sample/Sample/Base.lproj/Main.storyboard
  63. 2
      src/objective-c/examples/Sample/Sample/Info.plist
  64. 3
      src/objective-c/examples/Sample/Sample/ViewController.m
  65. 24
      src/objective-c/examples/Sample/SampleTests/Info.plist
  66. 0
      src/objective-c/generated_libraries/RemoteTestClient/Empty.pbobjc.h
  67. 0
      src/objective-c/generated_libraries/RemoteTestClient/Empty.pbobjc.m
  68. 0
      src/objective-c/generated_libraries/RemoteTestClient/Messages.pbobjc.h
  69. 0
      src/objective-c/generated_libraries/RemoteTestClient/Messages.pbobjc.m
  70. 0
      src/objective-c/generated_libraries/RemoteTestClient/RemoteTest.podspec
  71. 0
      src/objective-c/generated_libraries/RemoteTestClient/Test.pbobjc.h
  72. 0
      src/objective-c/generated_libraries/RemoteTestClient/Test.pbobjc.m
  73. 0
      src/objective-c/generated_libraries/RemoteTestClient/Test.pbrpc.h
  74. 0
      src/objective-c/generated_libraries/RemoteTestClient/Test.pbrpc.m
  75. 0
      src/objective-c/generated_libraries/RemoteTestClient/empty.proto
  76. 0
      src/objective-c/generated_libraries/RemoteTestClient/messages.proto
  77. 0
      src/objective-c/generated_libraries/RemoteTestClient/test.proto
  78. 0
      src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbobjc.h
  79. 0
      src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbobjc.m
  80. 0
      src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbrpc.h
  81. 0
      src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.pbrpc.m
  82. 0
      src/objective-c/generated_libraries/RouteGuideClient/Route_guide.podspec
  83. 0
      src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto
  84. 7
      src/objective-c/tests/GRPCClientTests.m
  85. 14
      src/objective-c/tests/InteropTests.m
  86. 11
      src/objective-c/tests/LocalClearTextTests.m
  87. 5
      src/objective-c/tests/Podfile
  88. 12
      src/objective-c/tests/Tests.xcodeproj/project.pbxproj
  89. 86
      src/python/src/grpc/_adapter/_c.c
  90. 61
      src/python/src/grpc/_adapter/_c/module.c
  91. 60
      src/python/src/grpc/_adapter/_c/types.c
  92. 271
      src/python/src/grpc/_adapter/_c/types.h
  93. 163
      src/python/src/grpc/_adapter/_c/types/call.c
  94. 134
      src/python/src/grpc/_adapter/_c/types/channel.c
  95. 286
      src/python/src/grpc/_adapter/_c/types/client_credentials.c
  96. 124
      src/python/src/grpc/_adapter/_c/types/completion_queue.c
  97. 183
      src/python/src/grpc/_adapter/_c/types/server.c
  98. 146
      src/python/src/grpc/_adapter/_c/types/server_credentials.c
  99. 460
      src/python/src/grpc/_adapter/_c/utility.c
  100. 188
      src/python/src/grpc/_adapter/_c_test.py
  101. Some files were not shown because too many files have changed in this diff Show More

40
BUILD

@ -143,7 +143,7 @@ cc_library(
"src/core/tsi/ssl_transport_security.h",
"src/core/tsi/transport_security.h",
"src/core/tsi/transport_security_interface.h",
"src/core/channel/census_filter.h",
"src/core/census/grpc_context.h",
"src/core/channel/channel_args.h",
"src/core/channel/channel_stack.h",
"src/core/channel/child_channel.h",
@ -192,12 +192,6 @@ cc_library(
"src/core/json/json_writer.h",
"src/core/profiling/timers.h",
"src/core/profiling/timers_preciseclock.h",
"src/core/statistics/census_interface.h",
"src/core/statistics/census_log.h",
"src/core/statistics/census_rpc_stats.h",
"src/core/statistics/census_tracing.h",
"src/core/statistics/hash_table.h",
"src/core/statistics/window_stats.h",
"src/core/surface/byte_buffer_queue.h",
"src/core/surface/call.h",
"src/core/surface/channel.h",
@ -230,6 +224,7 @@ cc_library(
"src/core/transport/stream_op.h",
"src/core/transport/transport.h",
"src/core/transport/transport_impl.h",
"src/core/census/context.h",
"src/core/httpcli/format_request.c",
"src/core/httpcli/httpcli.c",
"src/core/httpcli/httpcli_security_connector.c",
@ -253,7 +248,7 @@ cc_library(
"src/core/tsi/fake_transport_security.c",
"src/core/tsi/ssl_transport_security.c",
"src/core/tsi/transport_security.c",
"src/core/channel/census_filter.c",
"src/core/census/grpc_context.c",
"src/core/channel/channel_args.c",
"src/core/channel/channel_stack.c",
"src/core/channel/child_channel.c",
@ -305,12 +300,6 @@ cc_library(
"src/core/json/json_writer.c",
"src/core/profiling/basic_timers.c",
"src/core/profiling/stap_timers.c",
"src/core/statistics/census_init.c",
"src/core/statistics/census_log.c",
"src/core/statistics/census_rpc_stats.c",
"src/core/statistics/census_tracing.c",
"src/core/statistics/hash_table.c",
"src/core/statistics/window_stats.c",
"src/core/surface/byte_buffer.c",
"src/core/surface/byte_buffer_queue.c",
"src/core/surface/byte_buffer_reader.c",
@ -350,6 +339,8 @@ cc_library(
"src/core/transport/stream_op.c",
"src/core/transport/transport.c",
"src/core/transport/transport_op_string.c",
"src/core/census/context.c",
"src/core/census/initialize.c",
],
hdrs = [
"include/grpc/grpc_security.h",
@ -357,6 +348,7 @@ cc_library(
"include/grpc/byte_buffer_reader.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/census.h",
],
includes = [
"include",
@ -372,7 +364,7 @@ cc_library(
cc_library(
name = "grpc_unsecure",
srcs = [
"src/core/channel/census_filter.h",
"src/core/census/grpc_context.h",
"src/core/channel/channel_args.h",
"src/core/channel/channel_stack.h",
"src/core/channel/child_channel.h",
@ -421,12 +413,6 @@ cc_library(
"src/core/json/json_writer.h",
"src/core/profiling/timers.h",
"src/core/profiling/timers_preciseclock.h",
"src/core/statistics/census_interface.h",
"src/core/statistics/census_log.h",
"src/core/statistics/census_rpc_stats.h",
"src/core/statistics/census_tracing.h",
"src/core/statistics/hash_table.h",
"src/core/statistics/window_stats.h",
"src/core/surface/byte_buffer_queue.h",
"src/core/surface/call.h",
"src/core/surface/channel.h",
@ -459,8 +445,9 @@ cc_library(
"src/core/transport/stream_op.h",
"src/core/transport/transport.h",
"src/core/transport/transport_impl.h",
"src/core/census/context.h",
"src/core/surface/init_unsecure.c",
"src/core/channel/census_filter.c",
"src/core/census/grpc_context.c",
"src/core/channel/channel_args.c",
"src/core/channel/channel_stack.c",
"src/core/channel/child_channel.c",
@ -512,12 +499,6 @@ cc_library(
"src/core/json/json_writer.c",
"src/core/profiling/basic_timers.c",
"src/core/profiling/stap_timers.c",
"src/core/statistics/census_init.c",
"src/core/statistics/census_log.c",
"src/core/statistics/census_rpc_stats.c",
"src/core/statistics/census_tracing.c",
"src/core/statistics/hash_table.c",
"src/core/statistics/window_stats.c",
"src/core/surface/byte_buffer.c",
"src/core/surface/byte_buffer_queue.c",
"src/core/surface/byte_buffer_reader.c",
@ -557,12 +538,15 @@ cc_library(
"src/core/transport/stream_op.c",
"src/core/transport/transport.c",
"src/core/transport/transport_op_string.c",
"src/core/census/context.c",
"src/core/census/initialize.c",
],
hdrs = [
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/census.h",
],
includes = [
"include",

File diff suppressed because one or more lines are too long

@ -12,6 +12,19 @@
}
},
"filegroups": [
{
"name": "census",
"public_headers": [
"include/grpc/census.h"
],
"headers": [
"src/core/census/context.h"
],
"src": [
"src/core/census/context.c",
"src/core/census/initialize.c"
]
},
{
"name": "grpc++_base",
"public_headers": [
@ -91,7 +104,7 @@
"include/grpc/status.h"
],
"headers": [
"src/core/channel/census_filter.h",
"src/core/census/grpc_context.h",
"src/core/channel/channel_args.h",
"src/core/channel/channel_stack.h",
"src/core/channel/child_channel.h",
@ -140,12 +153,6 @@
"src/core/json/json_writer.h",
"src/core/profiling/timers.h",
"src/core/profiling/timers_preciseclock.h",
"src/core/statistics/census_interface.h",
"src/core/statistics/census_log.h",
"src/core/statistics/census_rpc_stats.h",
"src/core/statistics/census_tracing.h",
"src/core/statistics/hash_table.h",
"src/core/statistics/window_stats.h",
"src/core/surface/byte_buffer_queue.h",
"src/core/surface/call.h",
"src/core/surface/channel.h",
@ -180,7 +187,7 @@
"src/core/transport/transport_impl.h"
],
"src": [
"src/core/channel/census_filter.c",
"src/core/census/grpc_context.c",
"src/core/channel/channel_args.c",
"src/core/channel/channel_stack.c",
"src/core/channel/child_channel.c",
@ -232,12 +239,6 @@
"src/core/json/json_writer.c",
"src/core/profiling/basic_timers.c",
"src/core/profiling/stap_timers.c",
"src/core/statistics/census_init.c",
"src/core/statistics/census_log.c",
"src/core/statistics/census_rpc_stats.c",
"src/core/statistics/census_tracing.c",
"src/core/statistics/hash_table.c",
"src/core/statistics/window_stats.c",
"src/core/surface/byte_buffer.c",
"src/core/surface/byte_buffer_queue.c",
"src/core/surface/byte_buffer_reader.c",
@ -284,7 +285,6 @@
"src": [
"test/core/end2end/cq_verifier.c",
"test/core/iomgr/endpoint_tests.c",
"test/core/statistics/census_log_tests.c",
"test/core/util/grpc_profiler.c",
"test/core/util/parse_hexstring.c",
"test/core/util/port_posix.c",
@ -448,7 +448,8 @@
],
"baselib": true,
"filegroups": [
"grpc_base"
"grpc_base",
"census"
],
"secure": "yes",
"vs_project_guid": "{29D16885-7228-4C31-81ED-5F9187C7F2A9}"
@ -499,7 +500,8 @@
],
"baselib": true,
"filegroups": [
"grpc_base"
"grpc_base",
"census"
],
"secure": "no",
"vs_project_guid": "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}"
@ -801,147 +803,6 @@
"gpr"
]
},
{
"name": "census_hash_table_test",
"build": "test",
"language": "c",
"src": [
"test/core/statistics/hash_table_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "census_statistics_multiple_writers_circular_buffer_test",
"flaky": true,
"build": "test",
"language": "c",
"src": [
"test/core/statistics/multiple_writers_circular_buffer_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "census_statistics_multiple_writers_test",
"build": "test",
"language": "c",
"src": [
"test/core/statistics/multiple_writers_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "census_statistics_performance_test",
"build": "test",
"language": "c",
"src": [
"test/core/statistics/performance_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "census_statistics_quick_test",
"build": "test",
"language": "c",
"src": [
"test/core/statistics/quick_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "census_statistics_small_log_test",
"build": "test",
"language": "c",
"src": [
"test/core/statistics/small_log_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "census_stats_store_test",
"build": "executable",
"language": "c",
"src": [
"test/core/statistics/rpc_stats_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "census_stub_test",
"build": "test",
"language": "c",
"src": [
"test/core/statistics/census_stub_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "census_trace_store_test",
"build": "executable",
"language": "c",
"src": [
"test/core/statistics/trace_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "census_window_stats_test",
"build": "test",
"language": "c",
"src": [
"test/core/statistics/window_stats_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "chttp2_status_conversion_test",
"build": "test",

@ -1,13 +1,13 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
s.version = '0.0.1'
s.summary = 'Generic gRPC client library for iOS/OSX'
s.homepage = 'https://www.grpc.io'
s.version = '0.5.1'
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'http://www.grpc.io'
s.license = 'New BSD'
s.authors = { 'Jorge Canizales' => 'jcanizales@google.com',
'Michael Lumish' => 'mlumish@google.com' }
s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' }
# s.source = { :git => 'https://github.com/grpc/grpc.git', :tag => 'release-0_5_0' }
# s.source = { :git => 'https://github.com/grpc/grpc.git',
# :tag => 'release-0_9_1-objectivec-0.5.1' }
s.ios.deployment_target = '6.0'
s.osx.deployment_target = '10.8'
@ -15,7 +15,6 @@ Pod::Spec.new do |s|
s.subspec 'RxLibrary' do |rs|
rs.summary = 'Reactive Extensions library for iOS.'
rs.authors = { 'Jorge Canizales' => 'jcanizales@google.com' }
rs.source_files = 'src/objective-c/RxLibrary/*.{h,m}',
'src/objective-c/RxLibrary/transformations/*.{h,m}',
@ -25,16 +24,13 @@ Pod::Spec.new do |s|
s.subspec 'C-Core' do |cs|
cs.summary = 'Core cross-platform gRPC library, written in C.'
cs.authors = { 'Craig Tiller' => 'ctiller@google.com',
'David Klempner' => 'klempner@google.com',
'Nicolas Noble' => 'nnoble@google.com',
'Vijay Pai' => 'vpai@google.com',
'Yang Gao' => 'yangg@google.com' }
cs.source_files = 'src/core/**/*.{h,c}', 'include/grpc/*.h', 'include/grpc/**/*.h'
cs.private_header_files = 'src/core/**/*.h'
cs.header_mappings_dir = '.'
cs.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers/Build/gRPC" "$(PODS_ROOT)/Headers/Build/gRPC/include"' }
cs.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers/Build/gRPC" '
'"$(PODS_ROOT)/Headers/Build/gRPC/include"' }
cs.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w'
cs.requires_arc = false
cs.libraries = 'z'
@ -67,8 +63,6 @@ Pod::Spec.new do |s|
s.subspec 'GRPCClient' do |gs|
gs.summary = 'Objective-C wrapper around the core gRPC library.'
gs.authors = { 'Jorge Canizales' => 'jcanizales@google.com',
'Michael Lumish' => 'mlumish@google.com' }
gs.source_files = 'src/objective-c/GRPCClient/*.{h,m}',
'src/objective-c/GRPCClient/private/*.{h,m}'
@ -85,7 +79,6 @@ Pod::Spec.new do |s|
s.subspec 'ProtoRPC' do |ps|
ps.summary = 'RPC library for ProtocolBuffers, based on gRPC'
ps.authors = { 'Jorge Canizales' => 'jcanizales@google.com' }
ps.source_files = 'src/objective-c/ProtoRPC/*.{h,m}'

@ -76,9 +76,9 @@ class lock_guard {
template <class mutex>
class unique_lock : public lock_guard<mutex> {
public:
unique_lock(mutex &mu) : lock_guard(mu) { }
void lock() { lock_internal(); }
void unlock() { unlock_internal(); }
unique_lock(mutex &mu) : lock_guard<mutex>(mu) { }
void lock() { this->lock_internal(); }
void unlock() { this->unlock_internal(); }
};
class condition_variable {

@ -82,6 +82,10 @@ class thread {
thread_function_base *func_;
gpr_thd_id thd_;
bool joined_;
// Disallow copy and assign.
thread(const thread&);
void operator=(const thread&);
};
} // namespace grpc

@ -106,6 +106,10 @@ class ServerContext {
template <class R, class W>
friend class ::grpc::ServerReaderWriter;
// Prevent copying.
ServerContext(const ServerContext&);
ServerContext& operator=(const ServerContext&);
class CompletionOp;
void BeginCompletionOp(Call* call);

@ -0,0 +1,95 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 CENSUS_CENSUS_H
#define CENSUS_CENSUS_H
#include <grpc/grpc.h>
/* Identify census functionality that can be enabled via census_initialize(). */
enum census_functions {
CENSUS_NONE = 0, /* Do not enable census. */
CENSUS_TRACING = 1, /* Enable census tracing. */
CENSUS_STATS = 2, /* Enable Census stats collection. */
CENSUS_CPU = 4, /* Enable Census CPU usage collection. */
CENSUS_ALL = CENSUS_TRACING | CENSUS_STATS | CENSUS_CPU
};
/* Shutdown and startup census subsystem. The 'functions' argument should be
* the OR (|) of census_functions values. If census fails to initialize, then
* census_initialize() will return a non-zero value. It is an error to call
* census_initialize() more than once (without an intervening
* census_shutdown()). */
int census_initialize(int functions);
void census_shutdown();
/* Internally, Census relies on a context, which should be propagated across
* RPC's. From the RPC subsystems viewpoint, this is an opaque data structure.
* A context must be used as the first argument to all other census
* functions. Conceptually, contexts should be thought of as specific to
* single RPC/thread. The context can be serialized for passing across the
* wire. */
typedef struct census_context census_context;
/* This function is called by the RPC subsystem whenever it needs to get a
* serialized form of the current census context (presumably to pass across
* the wire). Arguments:
* 'buffer': pointer to memory into which serialized context will be placed
* 'buf_size': size of 'buffer'
*
* Returns: the number of bytes used in buffer if successful, or 0 if the
* buffer is of insufficient size.
*
* TODO(aveitch): determine how best to communicate required/max buffer size
* so caller doesn't have to guess. */
size_t census_context_serialize(const census_context *context, char *buffer,
size_t buf_size);
/* Create a new census context, possibly from a serialized buffer. If 'buffer'
* is non-NULL, it is assumed that it is a buffer encoded by
* census_context_serialize(). If `buffer` is NULL, a new, empty context is
* created. The decoded/new contest is returned in 'context'.
*
* Returns 0 if no errors, non-zero if buffer is incorrectly formatted, in
* which case a new empty context will be returned. */
int census_context_deserialize(const char *buffer, census_context **context);
/* The given context is destroyed. Once destroyed, using the context in
* future census calls will result in undefined behavior. */
void census_context_destroy(census_context *context);
#endif /* CENSUS_CENSUS_H */

@ -32,19 +32,20 @@
*/
#include <map>
#include <sstream>
#include "src/compiler/config.h"
#include "src/compiler/objective_c_generator.h"
#include "src/compiler/objective_c_generator_helpers.h"
#include "src/compiler/config.h"
#include <sstream>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
using ::google::protobuf::compiler::objectivec::ClassName;
using ::grpc::protobuf::io::Printer;
using ::grpc::protobuf::MethodDescriptor;
using ::grpc::protobuf::ServiceDescriptor;
using ::std::map;
using ::grpc::string;
using ::std::map;
namespace grpc_objective_c_generator {
namespace {
@ -69,7 +70,7 @@ void PrintMethodSignature(Printer *printer,
if (method->client_streaming()) {
printer->Print("RequestsWriter:(id<GRXWriter>)request");
} else {
printer->Print(vars, "Request:($prefix$$request_type$ *)request");
printer->Print(vars, "Request:($request_class$ *)request");
}
// TODO(jcanizales): Put this on a new line and align colons.
@ -78,8 +79,7 @@ void PrintMethodSignature(Printer *printer,
if (method->server_streaming()) {
printer->Print("BOOL done, ");
}
printer->Print(vars,
"$prefix$$response_type$ *response, NSError *error))handler");
printer->Print(vars, "$response_class$ *response, NSError *error))handler");
}
void PrintSimpleSignature(Printer *printer,
@ -99,12 +99,17 @@ void PrintAdvancedSignature(Printer *printer,
PrintMethodSignature(printer, method, vars);
}
inline map<string, string> GetMethodVars(const MethodDescriptor *method) {
return {{ "method_name", method->name() },
{ "request_type", method->input_type()->name() },
{ "response_type", method->output_type()->name() },
{ "request_class", ClassName(method->input_type()) },
{ "response_class", ClassName(method->output_type()) }};
}
void PrintMethodDeclarations(Printer *printer,
const MethodDescriptor *method,
map<string, string> vars) {
vars["method_name"] = method->name();
vars["request_type"] = method->input_type()->name();
vars["response_type"] = method->output_type()->name();
const MethodDescriptor *method) {
map<string, string> vars = GetMethodVars(method);
PrintProtoRpcDeclarationAsPragma(printer, method, vars);
@ -141,8 +146,7 @@ void PrintAdvancedImplementation(Printer *printer,
printer->Print("[GRXWriter writerWithValue:request]\n");
}
printer->Print(vars,
" responseClass:[$prefix$$response_type$ class]\n");
printer->Print(vars, " responseClass:[$response_class$ class]\n");
printer->Print(" responsesWriteable:[GRXWriteable ");
if (method->server_streaming()) {
@ -155,11 +159,8 @@ void PrintAdvancedImplementation(Printer *printer,
}
void PrintMethodImplementations(Printer *printer,
const MethodDescriptor *method,
map<string, string> vars) {
vars["method_name"] = method->name();
vars["request_type"] = method->input_type()->name();
vars["response_type"] = method->output_type()->name();
const MethodDescriptor *method) {
map<string, string> vars = GetMethodVars(method);
PrintProtoRpcDeclarationAsPragma(printer, method, vars);
@ -174,7 +175,7 @@ void PrintMethodImplementations(Printer *printer,
} // namespace
string GetHeader(const ServiceDescriptor *service, const string prefix) {
string GetHeader(const ServiceDescriptor *service) {
string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@ -184,19 +185,19 @@ string GetHeader(const ServiceDescriptor *service, const string prefix) {
printer.Print("@protocol GRXWriteable;\n");
printer.Print("@protocol GRXWriter;\n\n");
map<string, string> vars = {{"service_name", service->name()},
{"prefix", prefix}};
printer.Print(vars, "@protocol $prefix$$service_name$ <NSObject>\n\n");
map<string, string> vars = {{"service_class", ServiceClassName(service)}};
printer.Print(vars, "@protocol $service_class$ <NSObject>\n\n");
for (int i = 0; i < service->method_count(); i++) {
PrintMethodDeclarations(&printer, service->method(i), vars);
PrintMethodDeclarations(&printer, service->method(i));
}
printer.Print("@end\n\n");
printer.Print("// Basic service implementation, over gRPC, that only does"
" marshalling and parsing.\n");
printer.Print(vars, "@interface $prefix$$service_name$ :"
" ProtoService<$prefix$$service_name$>\n");
printer.Print(vars, "@interface $service_class$ :"
" ProtoService<$service_class$>\n");
printer.Print("- (instancetype)initWithHost:(NSString *)host"
" NS_DESIGNATED_INITIALIZER;\n");
printer.Print("@end\n");
@ -204,7 +205,7 @@ string GetHeader(const ServiceDescriptor *service, const string prefix) {
return output;
}
string GetSource(const ServiceDescriptor *service, const string prefix) {
string GetSource(const ServiceDescriptor *service) {
string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@ -212,15 +213,15 @@ string GetSource(const ServiceDescriptor *service, const string prefix) {
Printer printer(&output_stream, '$');
map<string, string> vars = {{"service_name", service->name()},
{"package", service->file()->package()},
{"prefix", prefix}};
{"service_class", ServiceClassName(service)},
{"package", service->file()->package()}};
printer.Print(vars,
"static NSString *const kPackageName = @\"$package$\";\n");
printer.Print(vars,
"static NSString *const kServiceName = @\"$service_name$\";\n\n");
printer.Print(vars, "@implementation $prefix$$service_name$\n\n");
printer.Print(vars, "@implementation $service_class$\n\n");
printer.Print("// Designated initializer\n");
printer.Print("- (instancetype)initWithHost:(NSString *)host {\n");
@ -236,7 +237,7 @@ string GetSource(const ServiceDescriptor *service, const string prefix) {
printer.Print("}\n\n\n");
for (int i = 0; i < service->method_count(); i++) {
PrintMethodImplementations(&printer, service->method(i), vars);
PrintMethodImplementations(&printer, service->method(i));
}
printer.Print("@end\n");

@ -38,15 +38,16 @@
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.
grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service,
const grpc::string prefix);
string GetHeader(const ServiceDescriptor *service);
// Returns the content to be included in the "global_scope" insertion point of
// the generated implementation file.
grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service,
const grpc::string prefix);
string GetSource(const ServiceDescriptor *service);
} // namespace grpc_objective_c_generator

@ -40,9 +40,19 @@
namespace grpc_objective_c_generator {
inline grpc::string MessageHeaderName(const grpc::protobuf::FileDescriptor *file) {
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

@ -77,7 +77,7 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
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, prefix);
declarations += grpc_objective_c_generator::GetHeader(service);
}
Write(context, file_name + ".pbrpc.h",
@ -95,7 +95,7 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
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, prefix);
definitions += grpc_objective_c_generator::GetSource(service);
}
Write(context, file_name + ".pbrpc.m", imports + '\n' + definitions);

@ -1,5 +1,4 @@
/*
*
<!---
* Copyright 2015, Google Inc.
* All rights reserved.
*
@ -28,50 +27,50 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 - a resource measurement and tracing system
#ifndef _ADAPTER__CALL_H_
#define _ADAPTER__CALL_H_
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/).
#include <Python.h>
#include <grpc/grpc.h>
## Concepts
#include "grpc/_adapter/_completion_queue.h"
#include "grpc/_adapter/_channel.h"
#include "grpc/_adapter/_server.h"
### Context
typedef struct {
PyObject_HEAD
### Operations
CompletionQueue *completion_queue;
Channel *channel;
Server *server;
### Tags
/* Legacy state. */
grpc_call_details call_details;
grpc_metadata_array recv_metadata;
grpc_metadata_array recv_trailing_metadata;
grpc_metadata *send_metadata;
size_t send_metadata_count;
grpc_metadata *send_trailing_metadata;
size_t send_trailing_metadata_count;
int adding_to_trailing;
### Metrics
grpc_byte_buffer *send_message;
grpc_byte_buffer *recv_message;
## API
grpc_status_code status;
char *status_details;
size_t status_details_capacity;
### Internal/RPC API
int cancelled;
### External/Client API
grpc_call *c_call;
} Call;
### RPC API
extern PyTypeObject pygrpc_CallType;
## Files in this directory
int pygrpc_add_call(PyObject *module);
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\_\*.
#endif /* _ADAPTER__CALL_H_ */

@ -31,19 +31,29 @@
*
*/
#ifndef _ADAPTER__CLIENT_CREDENTIALS_H_
#define _ADAPTER__CLIENT_CREDENTIALS_H_
#include "context.h"
#include <Python.h>
#include <grpc/grpc_security.h>
#include <string.h>
#include <grpc/census.h>
#include <grpc/support/alloc.h>
typedef struct {
PyObject_HEAD
grpc_credentials *c_client_credentials;
} ClientCredentials;
/* Placeholder implementation only. */
extern PyTypeObject pygrpc_ClientCredentialsType;
size_t census_context_serialize(const census_context *context, char *buffer,
size_t buf_size) {
/* TODO(aveitch): implement serialization */
return 0;
}
int pygrpc_add_client_credentials(PyObject *module);
int census_context_deserialize(const char *buffer, census_context **context) {
int ret = 0;
if (buffer != NULL) {
/* TODO(aveitch): implement deserialization. */
ret = 1;
}
*context = gpr_malloc(sizeof(census_context));
memset(*context, 0, sizeof(census_context));
return ret;
}
#endif /* _ADAPTER__CLIENT_CREDENTIALS_H_ */
void census_context_destroy(census_context *context) { gpr_free(context); }

@ -31,19 +31,19 @@
*
*/
#ifndef _ADAPTER__COMPLETION_QUEUE_H_
#define _ADAPTER__COMPLETION_QUEUE_H_
#ifndef GRPC_INTERNAL_CORE_CENSUS_CONTEXT_H
#define GRPC_INTERNAL_CORE_CENSUS_CONTEXT_H
#include <Python.h>
#include <grpc/grpc.h>
#include <grpc/census.h>
typedef struct {
PyObject_HEAD
grpc_completion_queue *c_completion_queue;
} CompletionQueue;
/* census_context is the in-memory representation of information needed to
* maintain tracing, RPC statistics and resource usage information. */
struct census_context {
gpr_uint64 op_id; /* Operation identifier - unique per-context */
gpr_uint64 trace_id; /* Globally unique trace identifier */
/* TODO(aveitch) Add census tags:
const census_tag_set *tags;
*/
};
extern PyTypeObject pygrpc_CompletionQueueType;
int pygrpc_add_completion_queue(PyObject *module);
#endif /* _ADAPTER__COMPLETION_QUEUE_H_ */
#endif /* GRPC_INTERNAL_CORE_CENSUS_CONTEXT_H */

@ -31,19 +31,15 @@
*
*/
#ifndef _ADAPTER__CHANNEL_H_
#define _ADAPTER__CHANNEL_H_
#include <grpc/census.h>
#include "src/core/census/grpc_context.h"
#include <Python.h>
#include <grpc/grpc.h>
void *grpc_census_context_create() {
census_context *context;
census_context_deserialize(NULL, &context);
return (void *)context;
}
typedef struct {
PyObject_HEAD
grpc_channel *c_channel;
} Channel;
extern PyTypeObject pygrpc_ChannelType;
int pygrpc_add_channel(PyObject *module);
#endif /* _ADAPTER__CHANNEL_H_ */
void grpc_census_context_destroy(void *context) {
census_context_destroy((census_context *)context);
}

@ -31,12 +31,12 @@
*
*/
#ifndef _ADAPTER__ERROR_H_
#define _ADAPTER__ERROR_H_
/* GRPC <--> CENSUS context interface */
#include <Python.h>
#include <grpc/grpc.h>
#ifndef CENSUS_GRPC_CONTEXT_H
#define CENSUS_GRPC_CONTEXT_H
const PyObject *pygrpc_translate_call_error(grpc_call_error call_error);
void *grpc_census_context_create();
void grpc_census_context_destroy(void *context);
#endif /* _ADAPTER__ERROR_H_ */
#endif /* CENSUS_GRPC_CONTEXT_H */

@ -31,21 +31,20 @@
*
*/
#ifndef _ADAPTER__SERVER_H_
#define _ADAPTER__SERVER_H_
#include <grpc/census.h>
#include <Python.h>
#include <grpc/grpc.h>
static int census_fns_enabled = CENSUS_NONE;
#include "grpc/_adapter/_completion_queue.h"
int census_initialize(int functions) {
if (census_fns_enabled != CENSUS_NONE) {
return 1;
}
if (functions != CENSUS_NONE) {
return 1;
} else {
census_fns_enabled = functions;
return 0;
}
}
typedef struct {
PyObject_HEAD
CompletionQueue *completion_queue;
grpc_server *c_server;
} Server;
int pygrpc_add_server(PyObject *module);
#endif /* _ADAPTER__SERVER_H_ */
void census_shutdown() { census_fns_enabled = CENSUS_NONE; }

@ -58,6 +58,9 @@ typedef struct {
gpr_uint8 sending_farewell;
/* have we sent farewell (goaway + disconnect) */
gpr_uint8 sent_farewell;
grpc_iomgr_closure finally_destroy_channel_closure;
grpc_iomgr_closure send_farewells_closure;
} lb_channel_data;
typedef struct { grpc_child_channel *channel; } lb_call_data;
@ -213,12 +216,16 @@ static void maybe_destroy_channel(grpc_child_channel *channel) {
lb_channel_data *chand = LINK_BACK_ELEM_FROM_CHANNEL(channel)->channel_data;
if (chand->destroyed && chand->disconnected && chand->active_calls == 0 &&
!chand->sending_farewell && !chand->calling_back) {
grpc_iomgr_add_callback(finally_destroy_channel, channel);
chand->finally_destroy_channel_closure.cb = finally_destroy_channel;
chand->finally_destroy_channel_closure.cb_arg = channel;
grpc_iomgr_add_callback(&chand->finally_destroy_channel_closure);
} else if (chand->destroyed && !chand->disconnected &&
chand->active_calls == 0 && !chand->sending_farewell &&
!chand->sent_farewell) {
chand->sending_farewell = 1;
grpc_iomgr_add_callback(send_farewells, channel);
chand->send_farewells_closure.cb = send_farewells;
chand->send_farewells_closure.cb_arg = channel;
grpc_iomgr_add_callback(&chand->send_farewells_closure);
}
}

@ -41,6 +41,7 @@ typedef struct {
grpc_endpoint *server;
} grpc_endpoint_pair;
grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(size_t read_slice_size);
grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
size_t read_slice_size);
#endif /* GRPC_INTERNAL_CORE_IOMGR_ENDPOINT_PAIR_H */

@ -44,6 +44,8 @@
#include <sys/socket.h>
#include "src/core/iomgr/tcp_posix.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
static void create_sockets(int sv[2]) {
@ -55,12 +57,21 @@ static void create_sockets(int sv[2]) {
GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
}
grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(size_t read_slice_size) {
grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
size_t read_slice_size) {
int sv[2];
grpc_endpoint_pair p;
char *final_name;
create_sockets(sv);
p.client = grpc_tcp_create(grpc_fd_create(sv[1]), read_slice_size);
p.server = grpc_tcp_create(grpc_fd_create(sv[0]), read_slice_size);
gpr_asprintf(&final_name, "%s:client", name);
p.client =
grpc_tcp_create(grpc_fd_create(sv[1], final_name), read_slice_size);
gpr_free(final_name);
gpr_asprintf(&final_name, "%s:server", name);
p.server =
grpc_tcp_create(grpc_fd_create(sv[0], final_name), read_slice_size);
gpr_free(final_name);
return p;
}

@ -77,12 +77,12 @@ static void create_sockets(SOCKET sv[2]) {
sv[0] = svr_sock;
}
grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(size_t read_slice_size) {
grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, size_t read_slice_size) {
SOCKET sv[2];
grpc_endpoint_pair p;
create_sockets(sv);
p.client = grpc_tcp_create(grpc_winsocket_create(sv[1]));
p.server = grpc_tcp_create(grpc_winsocket_create(sv[0]));
p.client = grpc_tcp_create(grpc_winsocket_create(sv[1], "endpoint:client"));
p.server = grpc_tcp_create(grpc_winsocket_create(sv[0], "endpoint:server"));
return p;
}

@ -41,7 +41,6 @@
#include <sys/socket.h>
#include <unistd.h>
#include "src/core/iomgr/iomgr_internal.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
@ -91,6 +90,7 @@ static grpc_fd *alloc_fd(int fd) {
gpr_mu_init(&r->set_state_mu);
gpr_mu_init(&r->watcher_mu);
}
gpr_atm_rel_store(&r->refst, 1);
gpr_atm_rel_store(&r->readst, NOT_READY);
gpr_atm_rel_store(&r->writest, NOT_READY);
@ -116,10 +116,9 @@ static void ref_by(grpc_fd *fd, int n) {
static void unref_by(grpc_fd *fd, int n) {
gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n);
if (old == n) {
close(fd->fd);
grpc_iomgr_add_callback(fd->on_done, fd->on_done_user_data);
grpc_iomgr_add_callback(&fd->on_done_closure);
freelist_fd(fd);
grpc_iomgr_unref();
grpc_iomgr_unregister_object(&fd->iomgr_object);
} else {
GPR_ASSERT(old > n);
}
@ -138,9 +137,9 @@ void grpc_fd_global_shutdown(void) {
static void do_nothing(void *ignored, int success) {}
grpc_fd *grpc_fd_create(int fd) {
grpc_fd *grpc_fd_create(int fd, const char *name) {
grpc_fd *r = alloc_fd(fd);
grpc_iomgr_ref();
grpc_iomgr_register_object(&r->iomgr_object, name);
grpc_pollset_add_fd(grpc_backup_pollset(), r);
return r;
}
@ -180,8 +179,8 @@ static void wake_all_watchers_locked(grpc_fd *fd) {
}
void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data) {
fd->on_done = on_done ? on_done : do_nothing;
fd->on_done_user_data = user_data;
grpc_iomgr_closure_init(&fd->on_done_closure, on_done ? on_done : do_nothing,
user_data);
shutdown(fd->fd, SHUT_RDWR);
ref_by(fd, 1); /* remove active status, but keep referenced */
gpr_mu_lock(&fd->watcher_mu);
@ -195,21 +194,20 @@ void grpc_fd_ref(grpc_fd *fd) { ref_by(fd, 2); }
void grpc_fd_unref(grpc_fd *fd) { unref_by(fd, 2); }
static void make_callback(grpc_iomgr_cb_func cb, void *arg, int success,
static void process_callback(grpc_iomgr_closure *closure, int success,
int allow_synchronous_callback) {
if (allow_synchronous_callback) {
cb(arg, success);
closure->cb(closure->cb_arg, success);
} else {
grpc_iomgr_add_delayed_callback(cb, arg, success);
grpc_iomgr_add_delayed_callback(closure, success);
}
}
static void make_callbacks(grpc_iomgr_closure *callbacks, size_t n, int success,
int allow_synchronous_callback) {
static void process_callbacks(grpc_iomgr_closure *callbacks, size_t n,
int success, int allow_synchronous_callback) {
size_t i;
for (i = 0; i < n; i++) {
make_callback(callbacks[i].cb, callbacks[i].cb_arg, success,
allow_synchronous_callback);
process_callback(callbacks + i, success, allow_synchronous_callback);
}
}
@ -234,10 +232,9 @@ static void notify_on(grpc_fd *fd, gpr_atm *st, grpc_iomgr_closure *closure,
/* swap was unsuccessful due to an intervening set_ready call.
Fall through to the READY code below */
case READY:
assert(gpr_atm_no_barrier_load(st) == READY);
GPR_ASSERT(gpr_atm_no_barrier_load(st) == READY);
gpr_atm_rel_store(st, NOT_READY);
make_callback(closure->cb, closure->cb_arg,
!gpr_atm_acq_load(&fd->shutdown),
process_callback(closure, !gpr_atm_acq_load(&fd->shutdown),
allow_synchronous_callback);
return;
default: /* WAITING */
@ -251,7 +248,7 @@ static void notify_on(grpc_fd *fd, gpr_atm *st, grpc_iomgr_closure *closure,
abort();
}
static void set_ready_locked(gpr_atm *st, grpc_iomgr_closure *callbacks,
static void set_ready_locked(gpr_atm *st, grpc_iomgr_closure **callbacks,
size_t *ncallbacks) {
gpr_intptr state = gpr_atm_acq_load(st);
@ -269,9 +266,9 @@ static void set_ready_locked(gpr_atm *st, grpc_iomgr_closure *callbacks,
Fall through to the WAITING code below */
state = gpr_atm_acq_load(st);
default: /* waiting */
assert(gpr_atm_no_barrier_load(st) != READY &&
gpr_atm_no_barrier_load(st) != NOT_READY);
callbacks[(*ncallbacks)++] = *(grpc_iomgr_closure *)state;
GPR_ASSERT(gpr_atm_no_barrier_load(st) != READY &&
gpr_atm_no_barrier_load(st) != NOT_READY);
callbacks[(*ncallbacks)++] = (grpc_iomgr_closure *)state;
gpr_atm_rel_store(st, NOT_READY);
return;
}
@ -282,25 +279,30 @@ static void set_ready(grpc_fd *fd, gpr_atm *st,
/* only one set_ready can be active at once (but there may be a racing
notify_on) */
int success;
grpc_iomgr_closure cb;
grpc_iomgr_closure* closure;
size_t ncb = 0;
gpr_mu_lock(&fd->set_state_mu);
set_ready_locked(st, &cb, &ncb);
set_ready_locked(st, &closure, &ncb);
gpr_mu_unlock(&fd->set_state_mu);
success = !gpr_atm_acq_load(&fd->shutdown);
make_callbacks(&cb, ncb, success, allow_synchronous_callback);
GPR_ASSERT(ncb <= 1);
if (ncb > 0) {
process_callbacks(closure, ncb, success, allow_synchronous_callback);
}
}
void grpc_fd_shutdown(grpc_fd *fd) {
grpc_iomgr_closure cb[2];
size_t ncb = 0;
gpr_mu_lock(&fd->set_state_mu);
GPR_ASSERT(!gpr_atm_no_barrier_load(&fd->shutdown));
gpr_atm_rel_store(&fd->shutdown, 1);
set_ready_locked(&fd->readst, cb, &ncb);
set_ready_locked(&fd->writest, cb, &ncb);
set_ready_locked(&fd->readst, &fd->shutdown_closures[0], &ncb);
set_ready_locked(&fd->writest, &fd->shutdown_closures[0], &ncb);
gpr_mu_unlock(&fd->set_state_mu);
make_callbacks(cb, ncb, 0, 0);
GPR_ASSERT(ncb <= 2);
process_callbacks(fd->shutdown_closures[0], ncb, 0 /* GPR_FALSE */,
0 /* GPR_FALSE */);
}
void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_closure *closure) {

@ -34,17 +34,12 @@
#ifndef GRPC_INTERNAL_CORE_IOMGR_FD_POSIX_H
#define GRPC_INTERNAL_CORE_IOMGR_FD_POSIX_H
#include "src/core/iomgr/iomgr.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/pollset.h"
#include <grpc/support/atm.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
typedef struct {
grpc_iomgr_cb_func cb;
void *cb_arg;
} grpc_iomgr_closure;
typedef struct grpc_fd grpc_fd;
typedef struct grpc_fd_watcher {
@ -96,15 +91,18 @@ struct grpc_fd {
gpr_atm readst;
gpr_atm writest;
grpc_iomgr_cb_func on_done;
void *on_done_user_data;
struct grpc_fd *freelist_next;
grpc_iomgr_closure on_done_closure;
grpc_iomgr_closure *shutdown_closures[2];
grpc_iomgr_object iomgr_object;
};
/* 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);
grpc_fd *grpc_fd_create(int fd, const char *name);
/* Releases fd to be asynchronously destroyed.
on_done is called when the underlying file descriptor is definitely close()d.

@ -37,25 +37,19 @@
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/alarm_internal.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/thd.h>
#include <grpc/support/sync.h>
typedef struct delayed_callback {
grpc_iomgr_cb_func cb;
void *cb_arg;
int success;
struct delayed_callback *next;
} delayed_callback;
static gpr_mu g_mu;
static gpr_cv g_rcv;
static delayed_callback *g_cbs_head = NULL;
static delayed_callback *g_cbs_tail = NULL;
static grpc_iomgr_closure *g_cbs_head = NULL;
static grpc_iomgr_closure *g_cbs_tail = NULL;
static int g_shutdown;
static int g_refs;
static gpr_event g_background_callback_executor_done;
static grpc_iomgr_object g_root_object;
/* Execute followup callbacks continuously.
Other threads may check in and help during pollset_work() */
@ -66,12 +60,11 @@ static void background_callback_executor(void *ignored) {
gpr_timespec short_deadline =
gpr_time_add(gpr_now(), gpr_time_from_millis(100));
if (g_cbs_head) {
delayed_callback *cb = g_cbs_head;
g_cbs_head = cb->next;
grpc_iomgr_closure *closure = g_cbs_head;
g_cbs_head = closure->next;
if (!g_cbs_head) g_cbs_tail = NULL;
gpr_mu_unlock(&g_mu);
cb->cb(cb->cb_arg, cb->success);
gpr_free(cb);
closure->cb(closure->cb_arg, closure->success);
gpr_mu_lock(&g_mu);
} else if (grpc_alarm_check(&g_mu, gpr_now(), &deadline)) {
} else {
@ -96,34 +89,48 @@ void grpc_iomgr_init(void) {
gpr_mu_init(&g_mu);
gpr_cv_init(&g_rcv);
grpc_alarm_list_init(gpr_now());
g_refs = 0;
g_root_object.next = g_root_object.prev = &g_root_object;
g_root_object.name = "root";
grpc_iomgr_platform_init();
gpr_event_init(&g_background_callback_executor_done);
gpr_thd_new(&id, background_callback_executor, NULL, NULL);
}
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;
}
void grpc_iomgr_shutdown(void) {
delayed_callback *cb;
grpc_iomgr_object *obj;
grpc_iomgr_closure *closure;
gpr_timespec shutdown_deadline =
gpr_time_add(gpr_now(), gpr_time_from_seconds(10));
gpr_mu_lock(&g_mu);
g_shutdown = 1;
while (g_cbs_head || g_refs) {
gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", g_refs,
while (g_cbs_head || g_root_object.next != &g_root_object) {
size_t nobjs = count_objects();
gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", nobjs,
g_cbs_head ? " and executing final callbacks" : "");
while (g_cbs_head) {
cb = g_cbs_head;
g_cbs_head = cb->next;
if (!g_cbs_head) g_cbs_tail = NULL;
gpr_mu_unlock(&g_mu);
cb->cb(cb->cb_arg, 0);
gpr_free(cb);
gpr_mu_lock(&g_mu);
if (g_cbs_head) {
do {
closure = g_cbs_head;
g_cbs_head = closure->next;
if (!g_cbs_head) g_cbs_tail = NULL;
gpr_mu_unlock(&g_mu);
closure->cb(closure->cb_arg, 0);
gpr_mu_lock(&g_mu);
} while (g_cbs_head);
continue;
}
if (g_refs) {
if (nobjs > 0) {
int timeout = 0;
gpr_timespec short_deadline = gpr_time_add(gpr_now(),
gpr_time_from_millis(100));
@ -137,7 +144,10 @@ void grpc_iomgr_shutdown(void) {
gpr_log(GPR_DEBUG,
"Failed to free %d iomgr objects before shutdown deadline: "
"memory leaks are likely",
g_refs);
count_objects());
for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) {
gpr_log(GPR_DEBUG, "LEAKED OBJECT: %s", obj->name);
}
break;
}
}
@ -153,56 +163,66 @@ void grpc_iomgr_shutdown(void) {
gpr_cv_destroy(&g_rcv);
}
void grpc_iomgr_ref(void) {
void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name) {
obj->name = gpr_strdup(name);
gpr_mu_lock(&g_mu);
++g_refs;
obj->next = &g_root_object;
obj->prev = obj->next->prev;
obj->next->prev = obj->prev->next = obj;
gpr_mu_unlock(&g_mu);
}
void grpc_iomgr_unref(void) {
void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) {
gpr_free(obj->name);
gpr_mu_lock(&g_mu);
if (0 == --g_refs) {
gpr_cv_signal(&g_rcv);
}
obj->next->prev = obj->prev;
obj->prev->next = obj->next;
gpr_cv_signal(&g_rcv);
gpr_mu_unlock(&g_mu);
}
void grpc_iomgr_add_delayed_callback(grpc_iomgr_cb_func cb, void *cb_arg,
int success) {
delayed_callback *dcb = gpr_malloc(sizeof(delayed_callback));
dcb->cb = cb;
dcb->cb_arg = cb_arg;
dcb->success = success;
void grpc_iomgr_closure_init(grpc_iomgr_closure *closure, grpc_iomgr_cb_func cb,
void *cb_arg) {
closure->cb = cb;
closure->cb_arg = cb_arg;
closure->next = NULL;
}
void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *closure, int success) {
closure->success = success;
gpr_mu_lock(&g_mu);
dcb->next = NULL;
closure->next = NULL;
if (!g_cbs_tail) {
g_cbs_head = g_cbs_tail = dcb;
g_cbs_head = g_cbs_tail = closure;
} else {
g_cbs_tail->next = dcb;
g_cbs_tail = dcb;
g_cbs_tail->next = closure;
g_cbs_tail = closure;
}
gpr_mu_unlock(&g_mu);
}
void grpc_iomgr_add_callback(grpc_iomgr_cb_func cb, void *cb_arg) {
grpc_iomgr_add_delayed_callback(cb, cb_arg, 1);
void grpc_iomgr_add_callback(grpc_iomgr_closure *closure) {
grpc_iomgr_add_delayed_callback(closure, 1 /* GPR_TRUE */);
}
int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success) {
int n = 0;
gpr_mu *retake_mu = NULL;
delayed_callback *cb;
grpc_iomgr_closure *closure;
for (;;) {
/* check for new work */
if (!gpr_mu_trylock(&g_mu)) {
break;
}
cb = g_cbs_head;
if (!cb) {
closure = g_cbs_head;
if (!closure) {
gpr_mu_unlock(&g_mu);
break;
}
g_cbs_head = cb->next;
g_cbs_head = closure->next;
if (!g_cbs_head) g_cbs_tail = NULL;
gpr_mu_unlock(&g_mu);
/* if we have a mutex to drop, do so before executing work */
@ -211,8 +231,7 @@ int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success) {
retake_mu = drop_mu;
drop_mu = NULL;
}
cb->cb(cb->cb_arg, success && cb->success);
gpr_free(cb);
closure->cb(closure->cb_arg, success && closure->success);
n++;
}
if (retake_mu) {

@ -34,14 +34,43 @@
#ifndef GRPC_INTERNAL_CORE_IOMGR_IOMGR_H
#define GRPC_INTERNAL_CORE_IOMGR_IOMGR_H
/* gRPC Callback definition */
/** gRPC Callback definition.
*
* \param arg Arbitrary input.
* \param success An indication on the state of the iomgr. On false, cleanup
* actions should be taken (eg, shutdown). */
typedef void (*grpc_iomgr_cb_func)(void *arg, int success);
/** A closure over a grpc_iomgr_cb_func. */
typedef struct grpc_iomgr_closure {
/** Bound callback. */
grpc_iomgr_cb_func cb;
/** Arguments to be passed to "cb". */
void *cb_arg;
/** Internal. A boolean indication to "cb" on the state of the iomgr.
* For instance, closures created during a shutdown would have this field set
* to false. */
int success;
/**< Internal. Do not touch */
struct grpc_iomgr_closure *next;
} grpc_iomgr_closure;
/** Initializes \a closure with \a cb and \a cb_arg. */
void grpc_iomgr_closure_init(grpc_iomgr_closure *closure, grpc_iomgr_cb_func cb,
void *cb_arg);
/** Initializes the iomgr. */
void grpc_iomgr_init(void);
/** Signals the intention to shutdown the iomgr. */
void grpc_iomgr_shutdown(void);
/* This function is called from within a callback or from anywhere else
and causes the invocation of a callback at some point in the future */
void grpc_iomgr_add_callback(grpc_iomgr_cb_func cb, void *cb_arg);
/** Registers a closure to be invoked at some point in the future.
*
* Can be called from within a callback or from anywhere else */
void grpc_iomgr_add_callback(grpc_iomgr_closure *closure);
#endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_H */

@ -35,15 +35,19 @@
#define GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H
#include "src/core/iomgr/iomgr.h"
#include "src/core/iomgr/iomgr_internal.h"
#include <grpc/support/sync.h>
typedef struct grpc_iomgr_object {
char *name;
struct grpc_iomgr_object *next;
struct grpc_iomgr_object *prev;
} grpc_iomgr_object;
int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success);
void grpc_iomgr_add_delayed_callback(grpc_iomgr_cb_func cb, void *cb_arg,
int success);
void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *iocb, int success);
void grpc_iomgr_ref(void);
void grpc_iomgr_unref(void);
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);
void grpc_iomgr_platform_shutdown(void);

@ -272,6 +272,7 @@ typedef struct grpc_unary_promote_args {
const grpc_pollset_vtable *original_vtable;
grpc_pollset *pollset;
grpc_fd *fd;
grpc_iomgr_closure promotion_closure;
} grpc_unary_promote_args;
static void unary_poll_do_promote(void *args, int success) {
@ -294,7 +295,7 @@ static void unary_poll_do_promote(void *args, int success) {
/* First we need to ensure that nobody is polling concurrently */
while (pollset->counter != 0) {
grpc_pollset_kick(pollset);
grpc_iomgr_add_callback(unary_poll_do_promote, up_args);
grpc_iomgr_add_callback(&up_args->promotion_closure);
gpr_mu_unlock(&pollset->mu);
return;
}
@ -378,7 +379,9 @@ static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) {
up_args->pollset = pollset;
up_args->fd = fd;
up_args->original_vtable = pollset->vtable;
grpc_iomgr_add_callback(unary_poll_do_promote, up_args);
up_args->promotion_closure.cb = unary_poll_do_promote;
up_args->promotion_closure.cb_arg = up_args;
grpc_iomgr_add_callback(&up_args->promotion_closure);
grpc_pollset_kick(pollset);
}

@ -66,15 +66,15 @@ int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
gpr_timespec now;
now = gpr_now();
if (gpr_time_cmp(now, deadline) > 0) {
return 0;
return 0 /* GPR_FALSE */;
}
if (grpc_maybe_call_delayed_callbacks(NULL, 1)) {
return 1;
if (grpc_maybe_call_delayed_callbacks(NULL, 1 /* GPR_TRUE */)) {
return 1 /* GPR_TRUE */;
}
if (grpc_alarm_check(NULL, now, &deadline)) {
return 1;
return 1 /* GPR_TRUE */;
}
return 0;
return 0 /* GPR_FALSE */;
}
void grpc_pollset_kick(grpc_pollset *p) { }

@ -55,6 +55,7 @@ typedef struct {
char *default_port;
grpc_resolve_cb cb;
void *arg;
grpc_iomgr_object iomgr_object;
} request;
grpc_resolved_addresses *grpc_blocking_resolve_address(
@ -153,9 +154,9 @@ static void do_request(void *rp) {
grpc_resolve_cb cb = r->cb;
gpr_free(r->name);
gpr_free(r->default_port);
grpc_iomgr_unregister_object(&r->iomgr_object);
gpr_free(r);
cb(arg, resolved);
grpc_iomgr_unref();
}
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
@ -166,14 +167,17 @@ void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
void grpc_resolve_address(const char *name, const char *default_port,
grpc_resolve_cb cb, void *arg) {
request *r = gpr_malloc(sizeof(request));
/*gpr_thd_id id;*/
grpc_iomgr_ref();
gpr_thd_id id;
char *tmp;
gpr_asprintf(&tmp, "resolve_address:name='%s':default_port='%s'", name,
default_port);
grpc_iomgr_register_object(&r->iomgr_object, tmp);
gpr_free(tmp);
r->name = gpr_strdup(name);
r->default_port = gpr_strdup(default_port);
r->cb = cb;
r->arg = arg;
/*gpr_thd_new(&id, do_request, r, NULL);*/
do_request(r);
gpr_thd_new(&id, do_request, r, NULL);
}
#endif

@ -54,6 +54,7 @@ typedef struct {
char *default_port;
grpc_resolve_cb cb;
void *arg;
grpc_iomgr_object iomgr_object;
} request;
grpc_resolved_addresses *grpc_blocking_resolve_address(
@ -135,7 +136,7 @@ static void do_request(void *rp) {
gpr_free(r->default_port);
gpr_free(r);
cb(arg, resolved);
grpc_iomgr_unref();
grpc_iomgr_unregister_object(&r->iomgr_object);
}
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
@ -147,7 +148,10 @@ void grpc_resolve_address(const char *name, const char *default_port,
grpc_resolve_cb cb, void *arg) {
request *r = gpr_malloc(sizeof(request));
gpr_thd_id id;
grpc_iomgr_ref();
const char *label;
gpr_asprintf(&label, "resolve:%s", name);
grpc_iomgr_register_object(&r->iomgr_object, label);
gpr_free(label);
r->name = gpr_strdup(name);
r->default_port = gpr_strdup(default_port);
r->cb = cb;

@ -39,18 +39,17 @@
#include <grpc/support/log.h>
#include "src/core/iomgr/iocp_windows.h"
#include "src/core/iomgr/iomgr.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/pollset.h"
#include "src/core/iomgr/pollset_windows.h"
#include "src/core/iomgr/socket_windows.h"
grpc_winsocket *grpc_winsocket_create(SOCKET socket) {
grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) {
grpc_winsocket *r = gpr_malloc(sizeof(grpc_winsocket));
memset(r, 0, sizeof(grpc_winsocket));
r->socket = socket;
gpr_mu_init(&r->state_mu);
grpc_iomgr_ref();
grpc_iomgr_register_object(&r->iomgr_object, name);
grpc_iocp_add_socket(r);
return r;
}
@ -64,13 +63,15 @@ int grpc_winsocket_shutdown(grpc_winsocket *socket) {
gpr_mu_lock(&socket->state_mu);
if (socket->read_info.cb) {
callbacks_set++;
grpc_iomgr_add_delayed_callback(socket->read_info.cb,
socket->read_info.opaque, 0);
grpc_iomgr_closure_init(&socket->shutdown_closure, socket->read_info.cb,
socket->read_info.opaque);
grpc_iomgr_add_delayed_callback(&socket->shutdown_closure, 0);
}
if (socket->write_info.cb) {
callbacks_set++;
grpc_iomgr_add_delayed_callback(socket->write_info.cb,
socket->write_info.opaque, 0);
grpc_iomgr_closure_init(&socket->shutdown_closure, socket->write_info.cb,
socket->write_info.opaque);
grpc_iomgr_add_delayed_callback(&socket->shutdown_closure, 0);
}
gpr_mu_unlock(&socket->state_mu);
return callbacks_set;
@ -90,7 +91,7 @@ void grpc_winsocket_orphan(grpc_winsocket *winsocket) {
grpc_winsocket_destroy(winsocket);
}
closesocket(socket);
grpc_iomgr_unref();
grpc_iomgr_unregister_object(&winsocket->iomgr_object);
}
void grpc_winsocket_destroy(grpc_winsocket *winsocket) {

@ -39,6 +39,8 @@
#include <grpc/support/sync.h>
#include <grpc/support/atm.h>
#include "src/core/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. */
@ -93,11 +95,16 @@ typedef struct grpc_winsocket {
there is a pending operation that the IO Completion Port will have to
wait for. The socket will be collected at that time. */
int orphan;
grpc_iomgr_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);
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. Returns the number of callbacks that got setup. */

@ -48,6 +48,7 @@
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/iomgr/socket_utils_posix.h"
#include "src/core/iomgr/tcp_posix.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
@ -185,6 +186,8 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
async_connect *ac;
struct sockaddr_in6 addr6_v4mapped;
struct sockaddr_in addr4_copy;
char *name;
char *addr_str;
/* Use dualstack sockets where available. */
if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
@ -211,24 +214,27 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
err = connect(fd, addr, addr_len);
} while (err < 0 && errno == EINTR);
grpc_sockaddr_to_string(&addr_str, addr, 1);
gpr_asprintf(&name, "tcp-client:%s", addr_str);
if (err >= 0) {
gpr_log(GPR_DEBUG, "instant connect");
cb(arg,
grpc_tcp_create(grpc_fd_create(fd), GRPC_TCP_DEFAULT_READ_SLICE_SIZE));
return;
cb(arg, grpc_tcp_create(grpc_fd_create(fd, name),
GRPC_TCP_DEFAULT_READ_SLICE_SIZE));
goto done;
}
if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
gpr_log(GPR_ERROR, "connect error: %s", strerror(errno));
gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
close(fd);
cb(arg, NULL);
return;
goto done;
}
ac = gpr_malloc(sizeof(async_connect));
ac->cb = cb;
ac->cb_arg = arg;
ac->fd = grpc_fd_create(fd);
ac->fd = grpc_fd_create(fd, name);
gpr_mu_init(&ac->mu);
ac->refs = 2;
ac->write_closure.cb = on_writable;
@ -236,6 +242,10 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now());
grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
done:
gpr_free(name);
gpr_free(addr_str);
}
#endif

@ -193,7 +193,7 @@ void grpc_tcp_client_connect(void(*cb)(void *arg, grpc_endpoint *tcp),
goto failure;
}
socket = grpc_winsocket_create(sock);
socket = grpc_winsocket_create(sock, "client");
info = &socket->write_info;
info->outstanding = 1;
success = ConnectEx(sock, addr, addr_len, NULL, 0, NULL, &info->overlapped);

@ -280,6 +280,8 @@ typedef struct {
grpc_iomgr_closure read_closure;
grpc_iomgr_closure write_closure;
grpc_iomgr_closure handle_read_closure;
} grpc_tcp;
static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success);
@ -443,7 +445,8 @@ static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb,
tcp->finished_edge = 0;
grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure);
} else {
grpc_iomgr_add_callback(grpc_tcp_handle_read, tcp);
tcp->handle_read_closure.cb_arg = tcp;
grpc_iomgr_add_callback(&tcp->handle_read_closure);
}
}
@ -592,6 +595,8 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size) {
tcp->read_closure.cb_arg = tcp;
tcp->write_closure.cb = grpc_tcp_handle_write;
tcp->write_closure.cb_arg = tcp;
tcp->handle_read_closure.cb = grpc_tcp_handle_read;
return &tcp->base;
}

@ -60,6 +60,7 @@
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/iomgr/socket_utils_posix.h"
#include "src/core/iomgr/tcp_posix.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
@ -281,6 +282,8 @@ static void on_read(void *arg, int success) {
for (;;) {
struct sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
char *addr_str;
char *name;
/* 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, (struct sockaddr *)&addr, &addrlen, 1, 1);
@ -299,9 +302,15 @@ static void on_read(void *arg, int success) {
grpc_set_socket_no_sigpipe_if_possible(fd);
sp->server->cb(
sp->server->cb_arg,
grpc_tcp_create(grpc_fd_create(fd), GRPC_TCP_DEFAULT_READ_SLICE_SIZE));
grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
sp->server->cb(sp->server->cb_arg,
grpc_tcp_create(grpc_fd_create(fd, name),
GRPC_TCP_DEFAULT_READ_SLICE_SIZE));
gpr_free(addr_str);
gpr_free(name);
}
abort();
@ -318,9 +327,13 @@ static int add_socket_to_server(grpc_tcp_server *s, int fd,
const struct sockaddr *addr, int addr_len) {
server_port *sp;
int port;
char *addr_str;
char *name;
port = prepare_socket(fd, addr, addr_len);
if (port >= 0) {
grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
gpr_mu_lock(&s->mu);
GPR_ASSERT(!s->cb && "must add ports before starting server");
/* append it to the list under a lock */
@ -331,11 +344,13 @@ static int add_socket_to_server(grpc_tcp_server *s, int fd,
sp = &s->ports[s->nports++];
sp->server = s;
sp->fd = fd;
sp->emfd = grpc_fd_create(fd);
sp->emfd = grpc_fd_create(fd, name);
memcpy(sp->addr.untyped, addr, addr_len);
sp->addr_len = addr_len;
GPR_ASSERT(sp->emfd);
gpr_mu_unlock(&s->mu);
gpr_free(addr_str);
gpr_free(name);
}
return port;

@ -270,7 +270,8 @@ static void on_accept(void *arg, int from_iocp) {
gpr_free(utf8_message);
closesocket(sock);
} else {
ep = grpc_tcp_create(grpc_winsocket_create(sock));
/* TODO(ctiller): add sockaddr address to label */
ep = grpc_tcp_create(grpc_winsocket_create(sock, "server"));
}
} else {
/* If we're not notified from the IOCP, it means we are asked to shutdown.
@ -336,7 +337,7 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
}
sp = &s->ports[s->nports++];
sp->server = s;
sp->socket = grpc_winsocket_create(sock);
sp->socket = grpc_winsocket_create(sock, "listener");
sp->shutting_down = 0;
sp->AcceptEx = AcceptEx;
sp->new_socket = INVALID_SOCKET;

@ -54,6 +54,7 @@
typedef struct {
grpc_credentials *creds;
grpc_credentials_metadata_cb cb;
grpc_iomgr_closure *on_simulated_token_fetch_done_closure;
void *user_data;
} grpc_credentials_metadata_request;
@ -65,6 +66,8 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds,
gpr_malloc(sizeof(grpc_credentials_metadata_request));
r->creds = grpc_credentials_ref(creds);
r->cb = cb;
r->on_simulated_token_fetch_done_closure =
gpr_malloc(sizeof(grpc_iomgr_closure));
r->user_data = user_data;
return r;
}
@ -72,6 +75,7 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds,
static void grpc_credentials_metadata_request_destroy(
grpc_credentials_metadata_request *r) {
grpc_credentials_unref(r->creds);
gpr_free(r->on_simulated_token_fetch_done_closure);
gpr_free(r);
}
@ -831,9 +835,11 @@ static void fake_oauth2_get_request_metadata(grpc_credentials *creds,
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds;
if (c->is_async) {
grpc_iomgr_add_callback(
on_simulated_token_fetch_done,
grpc_credentials_metadata_request_create(creds, cb, user_data));
grpc_credentials_metadata_request *cb_arg =
grpc_credentials_metadata_request_create(creds, cb, user_data);
grpc_iomgr_closure_init(cb_arg->on_simulated_token_fetch_done_closure,
on_simulated_token_fetch_done, cb_arg);
grpc_iomgr_add_callback(cb_arg->on_simulated_token_fetch_done_closure);
} else {
cb(user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
}

@ -31,6 +31,7 @@
*
*/
#include "src/core/census/grpc_context.h"
#include "src/core/surface/call.h"
#include "src/core/channel/channel_stack.h"
#include "src/core/iomgr/alarm.h"
@ -226,6 +227,7 @@ struct grpc_call {
gpr_slice_buffer incoming_message;
gpr_uint32 incoming_message_length;
grpc_iomgr_closure destroy_closure;
};
#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
@ -242,9 +244,9 @@ static int fill_send_ops(grpc_call *call, grpc_transport_op *op);
static void execute_op(grpc_call *call, grpc_transport_op *op);
static void recv_metadata(grpc_call *call, grpc_metadata_batch *metadata);
static void finish_read_ops(grpc_call *call);
static grpc_call_error cancel_with_status(
grpc_call *c, grpc_status_code status, const char *description,
gpr_uint8 locked);
static grpc_call_error cancel_with_status(grpc_call *c, grpc_status_code status,
const char *description,
gpr_uint8 locked);
grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
const void *server_transport_data,
@ -268,6 +270,8 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
if (call->is_client) {
call->request_set[GRPC_IOREQ_SEND_TRAILING_METADATA] = REQSET_DONE;
call->request_set[GRPC_IOREQ_SEND_STATUS] = REQSET_DONE;
call->context[GRPC_CONTEXT_TRACING].value = grpc_census_context_create();
call->context[GRPC_CONTEXT_TRACING].destroy = grpc_census_context_destroy;
}
GPR_ASSERT(add_initial_metadata_count < MAX_SEND_INITIAL_METADATA_COUNT);
for (i = 0; i < add_initial_metadata_count; i++) {
@ -367,7 +371,9 @@ void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) {
if (allow_immediate_deletion) {
destroy_call(c, 1);
} else {
grpc_iomgr_add_callback(destroy_call, c);
c->destroy_closure.cb = destroy_call;
c->destroy_closure.cb_arg = c;
grpc_iomgr_add_callback(&c->destroy_closure);
}
}
}
@ -403,7 +409,8 @@ static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); }
static int need_more_data(grpc_call *call) {
if (call->read_state == READ_STATE_STREAM_CLOSED) return 0;
return is_op_live(call, GRPC_IOREQ_RECV_INITIAL_METADATA) ||
(is_op_live(call, GRPC_IOREQ_RECV_MESSAGE) && grpc_bbq_empty(&call->incoming_queue)) ||
(is_op_live(call, GRPC_IOREQ_RECV_MESSAGE) &&
grpc_bbq_empty(&call->incoming_queue)) ||
is_op_live(call, GRPC_IOREQ_RECV_TRAILING_METADATA) ||
is_op_live(call, GRPC_IOREQ_RECV_STATUS) ||
is_op_live(call, GRPC_IOREQ_RECV_STATUS_DETAILS) ||
@ -556,13 +563,13 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op,
break;
case GRPC_IOREQ_RECV_INITIAL_METADATA:
GPR_SWAP(grpc_metadata_array, call->buffered_metadata[0],
*call->request_data[GRPC_IOREQ_RECV_INITIAL_METADATA]
.recv_metadata);
*call->request_data[GRPC_IOREQ_RECV_INITIAL_METADATA]
.recv_metadata);
break;
case GRPC_IOREQ_RECV_TRAILING_METADATA:
GPR_SWAP(grpc_metadata_array, call->buffered_metadata[1],
*call->request_data[GRPC_IOREQ_RECV_TRAILING_METADATA]
.recv_metadata);
*call->request_data[GRPC_IOREQ_RECV_TRAILING_METADATA]
.recv_metadata);
break;
case GRPC_IOREQ_OP_COUNT:
abort();
@ -676,9 +683,8 @@ static int add_slice_to_message(grpc_call *call, gpr_slice slice) {
}
/* we have to be reading a message to know what to do here */
if (!call->reading_message) {
cancel_with_status(
call, GRPC_STATUS_INVALID_ARGUMENT,
"Received payload data while not reading a message", 1);
cancel_with_status(call, GRPC_STATUS_INVALID_ARGUMENT,
"Received payload data while not reading a message", 1);
return 0;
}
/* append the slice to the incoming buffer */
@ -1025,9 +1031,9 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
return cancel_with_status(c, status, description, 0);
}
static grpc_call_error cancel_with_status(
grpc_call *c, grpc_status_code status, const char *description,
gpr_uint8 locked) {
static grpc_call_error cancel_with_status(grpc_call *c, grpc_status_code status,
const char *description,
gpr_uint8 locked) {
grpc_transport_op op;
grpc_mdstr *details =
description ? grpc_mdstr_from_string(c->metadata_context, description)
@ -1294,12 +1300,11 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
grpc_cq_begin_op(call->cq, call);
return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_func,
tag);
return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_func, tag);
}
void grpc_call_context_set(grpc_call *call, grpc_context_index elem, void *value,
void (*destroy)(void *value)) {
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);
}

@ -61,6 +61,7 @@ struct grpc_channel {
gpr_mu registered_call_mu;
registered_call *registered_calls;
grpc_iomgr_closure destroy_closure;
};
#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1))
@ -193,7 +194,9 @@ static void destroy_channel(void *p, int ok) {
void grpc_channel_internal_unref(grpc_channel *channel) {
if (gpr_unref(&channel->refs)) {
grpc_iomgr_add_callback(destroy_channel, channel);
channel->destroy_closure.cb = destroy_channel;
channel->destroy_closure.cb_arg = channel;
grpc_iomgr_add_callback(&channel->destroy_closure);
}
}

@ -195,9 +195,10 @@ grpc_channel *grpc_channel_create(const char *target,
const grpc_channel_filter *filters[MAX_FILTERS];
int n = 0;
filters[n++] = &grpc_client_surface_filter;
/* TODO(census)
if (grpc_channel_args_is_census_enabled(args)) {
filters[n++] = &grpc_client_census_filter;
}
} */
filters[n++] = &grpc_client_channel_filter;
GPR_ASSERT(n <= MAX_FILTERS);
channel = grpc_channel_create_from_filters(filters, n, args, mdctx, 1);

@ -31,11 +31,11 @@
*
*/
#include <grpc/census.h>
#include <grpc/grpc.h>
#include "src/core/channel/channel_stack.h"
#include "src/core/debug/trace.h"
#include "src/core/iomgr/iomgr.h"
#include "src/core/statistics/census_interface.h"
#include "src/core/profiling/timers.h"
#include "src/core/surface/call.h"
#include "src/core/surface/init.h"
@ -64,7 +64,9 @@ void grpc_init(void) {
grpc_security_pre_init();
grpc_iomgr_init();
grpc_tracer_init("GRPC_TRACE");
census_init();
if (census_initialize(CENSUS_NONE)) {
gpr_log(GPR_ERROR, "Could not initialize census.");
}
grpc_timers_global_init();
}
gpr_mu_unlock(&g_init_mu);

@ -234,9 +234,10 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
new_args_from_connector != NULL ? new_args_from_connector : args,
&connector_arg);
filters[n++] = &grpc_client_surface_filter;
/* TODO(census)
if (grpc_channel_args_is_census_enabled(args)) {
filters[n++] = &grpc_client_census_filter;
}
} */
filters[n++] = &grpc_client_channel_filter;
GPR_ASSERT(n <= MAX_FILTERS);
channel = grpc_channel_create_from_filters(filters, n, args_copy, mdctx, 1);

@ -122,6 +122,8 @@ struct channel_data {
channel_registered_method *registered_methods;
gpr_uint32 registered_method_slots;
gpr_uint32 registered_method_max_probes;
grpc_iomgr_closure finish_shutdown_channel_closure;
grpc_iomgr_closure finish_destroy_channel_closure;
};
typedef struct shutdown_tag {
@ -183,6 +185,8 @@ struct call_data {
void (*on_done_recv)(void *user_data, int success);
void *recv_user_data;
grpc_iomgr_closure kill_zombie_closure;
call_data **root[CALL_LIST_COUNT];
call_link links[CALL_LIST_COUNT];
};
@ -312,7 +316,9 @@ static void destroy_channel(channel_data *chand) {
GPR_ASSERT(chand->server != NULL);
orphan_channel(chand);
server_ref(chand->server);
grpc_iomgr_add_callback(finish_destroy_channel, chand);
chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
chand->finish_destroy_channel_closure.cb_arg = chand;
grpc_iomgr_add_callback(&chand->finish_destroy_channel_closure);
}
static void finish_start_new_rpc_and_unlock(grpc_server *server,
@ -444,7 +450,8 @@ static void server_on_recv(void *ptr, int success) {
gpr_mu_lock(&chand->server->mu);
if (calld->state == NOT_STARTED) {
calld->state = ZOMBIED;
grpc_iomgr_add_callback(kill_zombie, elem);
grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_iomgr_add_callback(&calld->kill_zombie_closure);
}
gpr_mu_unlock(&chand->server->mu);
break;
@ -452,11 +459,14 @@ static void server_on_recv(void *ptr, int success) {
gpr_mu_lock(&chand->server->mu);
if (calld->state == NOT_STARTED) {
calld->state = ZOMBIED;
grpc_iomgr_add_callback(kill_zombie, elem);
grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_iomgr_add_callback(&calld->kill_zombie_closure);
} else if (calld->state == PENDING) {
call_list_remove(calld, PENDING_START);
calld->state = ZOMBIED;
grpc_iomgr_add_callback(kill_zombie, elem);
grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_iomgr_add_callback(&calld->kill_zombie_closure);
}
if (call_list_remove(calld, ALL_CALLS)) {
maybe_finish_shutdown(chand->server);
@ -533,7 +543,9 @@ static void finish_shutdown_channel(void *cd, int success) {
static void shutdown_channel(channel_data *chand) {
grpc_channel_internal_ref(chand->channel);
grpc_iomgr_add_callback(finish_shutdown_channel, chand);
chand->finish_shutdown_channel_closure.cb = finish_shutdown_channel;
chand->finish_shutdown_channel_closure.cb_arg = chand;
grpc_iomgr_add_callback(&chand->finish_shutdown_channel_closure);
}
static void init_call_elem(grpc_call_element *elem,
@ -621,9 +633,15 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
}
static const grpc_channel_filter server_surface_filter = {
server_start_transport_op, channel_op, sizeof(call_data), init_call_elem,
destroy_call_elem, sizeof(channel_data), init_channel_elem,
destroy_channel_elem, "server",
server_start_transport_op,
channel_op,
sizeof(call_data),
init_call_elem,
destroy_call_elem,
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
"server",
};
void grpc_server_register_completion_queue(grpc_server *server,
@ -643,7 +661,9 @@ grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters,
size_t filter_count,
const grpc_channel_args *args) {
size_t i;
int census_enabled = grpc_channel_args_is_census_enabled(args);
/* TODO(census): restore this once we finalize census filter etc.
int census_enabled = grpc_channel_args_is_census_enabled(args); */
int census_enabled = 0;
grpc_server *server = gpr_malloc(sizeof(grpc_server));
@ -668,9 +688,10 @@ grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters,
server->channel_filters =
gpr_malloc(server->channel_filter_count * sizeof(grpc_channel_filter *));
server->channel_filters[0] = &server_surface_filter;
/* TODO(census): restore this once we rework census filter
if (census_enabled) {
server->channel_filters[1] = &grpc_server_census_filter;
}
} */
for (i = 0; i < filter_count; i++) {
server->channel_filters[i + 1 + census_enabled] = filters[i];
}
@ -969,9 +990,10 @@ void grpc_server_destroy(grpc_server *server) {
while ((calld = call_list_remove_head(&server->lists[PENDING_START],
PENDING_START)) != NULL) {
calld->state = ZOMBIED;
grpc_iomgr_add_callback(
kill_zombie,
grpc_iomgr_closure_init(
&calld->kill_zombie_closure, kill_zombie,
grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
grpc_iomgr_add_callback(&calld->kill_zombie_closure);
}
for (c = server->root_channel_data.next; c != &server->root_channel_data;

@ -219,10 +219,10 @@ static int state_index(int bitofs, symset syms, int *isnew) {
emit - the symbol to emit on this nibble (or -1 if no symbol has been
found)
syms - the set of symbols that could be matched */
static void build_dec_tbl(int state, int nibble, int nibbits, int bitofs,
static void build_dec_tbl(int state, int nibble, int nibbits, unsigned bitofs,
int emit, symset syms) {
int i;
int bit;
unsigned bit;
/* If we have four bits in the nibble we're looking at, then we can fill in
a slot in the lookup tables. */
@ -338,7 +338,7 @@ static void generate_base64_inverse_table(void) {
static const char alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
unsigned char inverse[256];
int i;
unsigned i;
memset(inverse, 255, sizeof(inverse));
for (i = 0; i < strlen(alphabet); i++) {

@ -60,7 +60,7 @@ void ThreadPool::ThreadFunc() {
ThreadPool::ThreadPool(int num_threads) : shutdown_(false) {
for (int i = 0; i < num_threads; i++) {
threads_.push_back(grpc::thread(&ThreadPool::ThreadFunc, this));
threads_.push_back(new grpc::thread(&ThreadPool::ThreadFunc, this));
}
}
@ -71,7 +71,8 @@ ThreadPool::~ThreadPool() {
cv_.notify_all();
}
for (auto t = threads_.begin(); t != threads_.end(); t++) {
t->join();
(*t)->join();
delete *t;
}
}

@ -57,7 +57,7 @@ class ThreadPool GRPC_FINAL : public ThreadPoolInterface {
grpc::condition_variable cv_;
bool shutdown_;
std::queue<std::function<void()>> callbacks_;
std::vector<grpc::thread> threads_;
std::vector<grpc::thread*> threads_;
void ThreadFunc();
};

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit.Runners" version="2.6.4" />
</packages>

@ -5,19 +5,19 @@
<title>gRPC C# Auth</title>
<summary>Auth library for C# implementation of gRPC - an RPC library and framework</summary>
<description>Auth library for C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
<version>0.5.0</version>
<version>0.5.1</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>Release 0.5.0 of gRPC C#</releaseNotes>
<releaseNotes>Release 0.5.1 of gRPC C#</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2 Auth OAuth2</tags>
<dependencies>
<dependency id="BouncyCastle" version="1.7.0" />
<dependency id="Google.Apis.Auth" version="1.9.1" />
<dependency id="Grpc.Core" version="0.5.0" />
<dependency id="Grpc.Core" version="0.5.1" />
</dependencies>
</metadata>
<files>

@ -5,19 +5,19 @@
<title>gRPC C# Core</title>
<summary>Core C# implementation of gRPC - an RPC library and framework</summary>
<description>Core C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
<version>0.5.0</version>
<version>0.5.1</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>Release 0.5.0 of gRPC C#</releaseNotes>
<releaseNotes>Release 0.5.1 of gRPC C#</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
<dependencies>
<dependency id="Microsoft.Bcl.Immutable" version="1.0.34" />
<dependency id="Ix-Async" version="1.2.3" />
<dependency id="grpc.native.csharp_ext" version="0.9.0.0" />
<dependency id="grpc.native.csharp_ext" version="0.9.1" />
</dependencies>
</metadata>
<files>

@ -5,13 +5,13 @@
<title>gRPC C# Tools</title>
<summary>Tools for C# implementation of gRPC - an RPC library and framework</summary>
<description>Precompiled Windows binaries for generating protocol buffer messages and gRPC client/server code</description>
<version>0.5.0</version>
<version>0.5.1</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version 0.5.0</releaseNotes>
<releaseNotes>protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version 0.5.1</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
</metadata>

@ -5,17 +5,17 @@
<title>gRPC C#</title>
<summary>C# implementation of gRPC - an RPC library and framework</summary>
<description>C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
<version>0.5.0.1</version>
<version>0.5.1</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>Release 0.5.0 of gRPC C#</releaseNotes>
<releaseNotes>Release 0.5.1 of gRPC C#</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
<dependencies>
<dependency id="Grpc.Core" version="0.5.0" />
<dependency id="Grpc.Core" version="0.5.1" />
</dependencies>
</metadata>
<files/>

@ -1,6 +1,8 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
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}") = "Grpc.Examples", "Grpc.Examples\Grpc.Examples.csproj", "{7DC1433E-3225-42C7-B7EA-546D56E27A4B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Core", "Grpc.Core\Grpc.Core.csproj", "{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}"
@ -21,52 +23,60 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Examples.MathServer",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Auth", "Grpc.Auth\Grpc.Auth.csproj", "{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{B5B87121-35FE-49D1-8CB1-8A91AAA398A9}"
ProjectSection(SolutionItems) = preProject
.nuget\packages.config = .nuget\packages.config
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|x86.ActiveCfg = Debug|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|x86.Build.0 = Debug|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|x86.ActiveCfg = Release|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|x86.Build.0 = Release|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|x86.ActiveCfg = Debug|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|x86.Build.0 = Debug|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|x86.ActiveCfg = Release|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|x86.Build.0 = Release|x86
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.ActiveCfg = Debug|x86
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.Build.0 = Debug|x86
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.ActiveCfg = Release|x86
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.Build.0 = Release|x86
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|x86.ActiveCfg = Debug|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|x86.Build.0 = Debug|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|x86.ActiveCfg = Release|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|x86.Build.0 = Release|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.ActiveCfg = Debug|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.Build.0 = Debug|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.ActiveCfg = Release|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.Build.0 = Release|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|x86.ActiveCfg = Debug|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|x86.Build.0 = Debug|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|x86.ActiveCfg = Release|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|x86.Build.0 = Release|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|x86.ActiveCfg = Debug|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|x86.Build.0 = Debug|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|x86.ActiveCfg = Release|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|x86.Build.0 = Release|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.ActiveCfg = Debug|x86
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|x86.Build.0 = Debug|x86
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.ActiveCfg = Release|x86
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|x86.Build.0 = Release|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.ActiveCfg = Debug|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.Build.0 = Debug|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.ActiveCfg = Release|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.Build.0 = Release|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|x86.ActiveCfg = Debug|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|x86.Build.0 = Debug|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|x86.ActiveCfg = Release|x86
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|x86.Build.0 = Release|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|x86.ActiveCfg = Debug|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|x86.Build.0 = Debug|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.ActiveCfg = Release|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.Build.0 = Release|x86
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.ActiveCfg = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.Build.0 = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.ActiveCfg = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.Build.0 = Release|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.ActiveCfg = Debug|x86
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.Build.0 = Debug|x86
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.ActiveCfg = Release|x86
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.Build.0 = Release|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.ActiveCfg = Debug|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.Build.0 = Debug|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.ActiveCfg = Release|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.Build.0 = Release|x86
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.ActiveCfg = Debug|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|x86.Build.0 = Debug|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.ActiveCfg = Release|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|x86.Build.0 = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.ActiveCfg = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.Build.0 = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.ActiveCfg = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = Grpc.Examples\Grpc.Examples.csproj

@ -1,11 +1,15 @@
@rem Convenience script to build gRPC C# from command line
setlocal
@rem enter this directory
cd /d %~dp0
@rem Set VS variables (uses Visual Studio 2013)
@call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86
@rem Build the C# native extension
msbuild ..\..\vsprojects\grpc.sln /t:grpc_csharp_ext || goto :error
msbuild ..\..\vsprojects\grpc.sln /t:grpc_csharp_ext /p:PlatformToolset=v120 || goto :error
msbuild Grpc.sln /p:Configuration=Debug || goto :error
msbuild Grpc.sln /p:Configuration=Release || goto :error

@ -35,21 +35,90 @@
#include <grpc/support/alloc.h>
#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 and the given key.
- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key;
@end
@implementation NSData (GRPCMetadata)
+ (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata {
// TODO(jcanizales): Should we use a non-copy constructor?
return [self dataWithBytes:metadata->value length:metadata->value_length];
}
- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key {
// TODO(jcanizales): Encode Unicode chars as ASCII.
metadata->key = [key stringByAppendingString:@"-bin"].UTF8String;
metadata->value = self.bytes;
metadata->value_length = 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 and the given key.
- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key;
@end
@implementation NSString (GRPCMetadata)
+ (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata {
return [[self alloc] initWithBytes:metadata->value
length:metadata->value_length
encoding:NSASCIIStringEncoding];
}
- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key {
if ([key hasSuffix:@"-bin"]) {
// Disallow this, as at best it will confuse the server. If the app really needs to send a
// textual header with a name ending in "-bin", it can be done by removing the suffix and
// encoding the NSString as a NSData object.
//
// Why raise an exception: In the most common case, the developer knows this won't happen in
// their code, so the exception isn't triggered. In the rare cases when the developer can't
// tell, it's easy enough to add a sanitizing filter before the header is set. There, the
// developer can choose whether to drop such a header, or trim its name. Doing either ourselves,
// silently, would be very unintuitive for the user.
[NSException raise:NSInvalidArgumentException
format:@"Metadata keys ending in '-bin' are reserved for NSData values."];
}
// TODO(jcanizales): Encode Unicode chars as ASCII.
metadata->key = key.UTF8String;
metadata->value = self.UTF8String;
metadata->value_length = self.length;
}
@end
#pragma mark Category for metadata arrays
@implementation NSDictionary (GRPC)
+ (instancetype)grpc_dictionaryFromMetadata:(grpc_metadata *)entries count:(size_t)count {
NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithCapacity:count];
for (grpc_metadata *entry = entries; entry < entries + count; entry++) {
// TODO(jcanizales): Verify in a C library test that it's converting header names to lower case automatically.
NSString *name = [NSString stringWithUTF8String:entry->key];
// TODO(jcanizales): Verify in a C library test that it's converting header names to lower case
// automatically.
NSString *name = [NSString stringWithCString:entry->key encoding:NSASCIIStringEncoding];
if (!name) {
// log?
continue;
}
id value;
if ([name hasSuffix:@"-bin"]) {
name = [name substringToIndex:name.length - 4];
value = [NSData grpc_dataFromMetadataValue:entry];
} else {
value = [NSString grpc_stringFromMetadataValue:entry];
}
if (!metadata[name]) {
metadata[name] = [NSMutableArray array];
}
// TODO(jcanizales): Should we use a non-copy constructor?
[metadata[name] addObject:[NSData dataWithBytes:entry->value
length:entry->value_length]];
[metadata[name] addObject:value];
}
return metadata;
}
@ -60,11 +129,8 @@
for (id key in self) {
id value = self[key];
grpc_metadata *current = &metadata[i];
current->key = [key UTF8String];
if ([value isKindOfClass:[NSData class]]) {
current->value = [value bytes];
} else if ([value isKindOfClass:[NSString class]]) {
current->value = [value UTF8String];
if ([value respondsToSelector:@selector(grpc_initMetadata:withKey:)]) {
[value grpc_initMetadata:current withKey:key];
} else {
[NSException raise:NSInvalidArgumentException
format:@"Metadata values must be NSString or NSData."];

@ -3,13 +3,7 @@ platform :ios, '8.0'
pod 'gRPC', :path => "../../../.."
pod 'Protobuf', :git => 'https://github.com/google/protobuf.git'
pod 'Route_guide', :path => "RouteGuideClient"
pod 'RemoteTest', :path => "RemoteTestClient"
link_with 'Sample', 'SampleTests'
pod 'RemoteTest', :path => "../../generated_libraries/RemoteTestClient"
target 'Sample' do
end
target 'SampleTests' do
end

@ -7,33 +7,16 @@
objects = {
/* Begin PBXBuildFile section */
60BBBBB15823BBF7639D7AA9 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; };
6340F0491AE66E3300FB6A3D /* RemoteProtoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6340F0481AE66E3300FB6A3D /* RemoteProtoTests.m */; };
6356D1DE1AC11FE00075FBBC /* RemoteTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6356D1DD1AC11FE00075FBBC /* RemoteTests.m */; };
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 */; };
6369A27E1A9322E20015FC5C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27C1A9322E20015FC5C /* LaunchScreen.xib */; };
6369A28A1A9322E20015FC5C /* SampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2891A9322E20015FC5C /* SampleTests.m */; };
FC81FE63CA655031F3524EC0 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
6369A2841A9322E20015FC5C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6369A2621A9322E20015FC5C /* Project object */;
proxyType = 1;
remoteGlobalIDString = 6369A2691A9322E20015FC5C;
remoteInfo = Sample;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
2DC7B7C4C0410F43B9621631 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
6340F0481AE66E3300FB6A3D /* RemoteProtoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteProtoTests.m; sourceTree = "<group>"; };
6356D1DD1AC11FE00075FBBC /* RemoteTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteTests.m; sourceTree = "<group>"; };
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 = "<group>"; };
6369A26F1A9322E20015FC5C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@ -43,10 +26,6 @@
6369A2751A9322E20015FC5C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
6369A2781A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
6369A27A1A9322E20015FC5C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
6369A27D1A9322E20015FC5C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
6369A2831A9322E20015FC5C /* SampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
6369A2881A9322E20015FC5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6369A2891A9322E20015FC5C /* SampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleTests.m; sourceTree = "<group>"; };
AC29DD6FCDF962F519FEBB0D /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
C68330F8D451CC6ACEABA09F /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -60,14 +39,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
6369A2801A9322E20015FC5C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
60BBBBB15823BBF7639D7AA9 /* libPods.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@ -75,7 +46,6 @@
isa = PBXGroup;
children = (
6369A26C1A9322E20015FC5C /* Sample */,
6369A2861A9322E20015FC5C /* SampleTests */,
6369A26B1A9322E20015FC5C /* Products */,
AB3331C9AE6488E61B2B094E /* Pods */,
C4C2C5219053E079C9EFB930 /* Frameworks */,
@ -86,7 +56,6 @@
isa = PBXGroup;
children = (
6369A26A1A9322E20015FC5C /* Sample.app */,
6369A2831A9322E20015FC5C /* SampleTests.xctest */,
);
name = Products;
sourceTree = "<group>";
@ -100,7 +69,6 @@
6369A2751A9322E20015FC5C /* ViewController.m */,
6369A2771A9322E20015FC5C /* Main.storyboard */,
6369A27A1A9322E20015FC5C /* Images.xcassets */,
6369A27C1A9322E20015FC5C /* LaunchScreen.xib */,
6369A26D1A9322E20015FC5C /* Supporting Files */,
);
path = Sample;
@ -115,25 +83,6 @@
name = "Supporting Files";
sourceTree = "<group>";
};
6369A2861A9322E20015FC5C /* SampleTests */ = {
isa = PBXGroup;
children = (
6340F0481AE66E3300FB6A3D /* RemoteProtoTests.m */,
6369A2891A9322E20015FC5C /* SampleTests.m */,
6369A2871A9322E20015FC5C /* Supporting Files */,
6356D1DD1AC11FE00075FBBC /* RemoteTests.m */,
);
path = SampleTests;
sourceTree = "<group>";
};
6369A2871A9322E20015FC5C /* Supporting Files */ = {
isa = PBXGroup;
children = (
6369A2881A9322E20015FC5C /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
AB3331C9AE6488E61B2B094E /* Pods */ = {
isa = PBXGroup;
children = (
@ -173,26 +122,6 @@
productReference = 6369A26A1A9322E20015FC5C /* Sample.app */;
productType = "com.apple.product-type.application";
};
6369A2821A9322E20015FC5C /* SampleTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6369A2901A9322E20015FC5C /* Build configuration list for PBXNativeTarget "SampleTests" */;
buildPhases = (
75C393B2FDC60A22B2121058 /* Check Pods Manifest.lock */,
6369A27F1A9322E20015FC5C /* Sources */,
6369A2801A9322E20015FC5C /* Frameworks */,
6369A2811A9322E20015FC5C /* Resources */,
7B8CDC152F76D6014A96C798 /* Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
6369A2851A9322E20015FC5C /* PBXTargetDependency */,
);
name = SampleTests;
productName = SampleTests;
productReference = 6369A2831A9322E20015FC5C /* SampleTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@ -205,10 +134,6 @@
6369A2691A9322E20015FC5C = {
CreatedOnToolsVersion = 6.1.1;
};
6369A2821A9322E20015FC5C = {
CreatedOnToolsVersion = 6.1.1;
TestTargetID = 6369A2691A9322E20015FC5C;
};
};
};
buildConfigurationList = 6369A2651A9322E20015FC5C /* Build configuration list for PBXProject "Sample" */;
@ -225,7 +150,6 @@
projectRoot = "";
targets = (
6369A2691A9322E20015FC5C /* Sample */,
6369A2821A9322E20015FC5C /* SampleTests */,
);
};
/* End PBXProject section */
@ -236,18 +160,10 @@
buildActionMask = 2147483647;
files = (
6369A2791A9322E20015FC5C /* Main.storyboard in Resources */,
6369A27E1A9322E20015FC5C /* LaunchScreen.xib in Resources */,
6369A27B1A9322E20015FC5C /* Images.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6369A2811A9322E20015FC5C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@ -281,36 +197,6 @@
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;
};
75C393B2FDC60A22B2121058 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
7B8CDC152F76D6014A96C798 /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -324,26 +210,8 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
6369A27F1A9322E20015FC5C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6369A28A1A9322E20015FC5C /* SampleTests.m in Sources */,
6340F0491AE66E3300FB6A3D /* RemoteProtoTests.m in Sources */,
6356D1DE1AC11FE00075FBBC /* RemoteTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
6369A2851A9322E20015FC5C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6369A2691A9322E20015FC5C /* Sample */;
targetProxy = 6369A2841A9322E20015FC5C /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
6369A2771A9322E20015FC5C /* Main.storyboard */ = {
isa = PBXVariantGroup;
@ -353,14 +221,6 @@
name = Main.storyboard;
sourceTree = "<group>";
};
6369A27C1A9322E20015FC5C /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
6369A27D1A9322E20015FC5C /* Base */,
);
name = LaunchScreen.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
@ -464,42 +324,6 @@
};
name = Release;
};
6369A2911A9322E20015FC5C /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = AC29DD6FCDF962F519FEBB0D /* Pods.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = SampleTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sample.app/Sample";
};
name = Debug;
};
6369A2921A9322E20015FC5C /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C68330F8D451CC6ACEABA09F /* Pods.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = SampleTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sample.app/Sample";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@ -521,15 +345,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6369A2901A9322E20015FC5C /* Build configuration list for PBXNativeTarget "SampleTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6369A2911A9322E20015FC5C /* Debug */,
6369A2921A9322E20015FC5C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 6369A2621A9322E20015FC5C /* Project object */;

@ -34,8 +34,5 @@
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

@ -33,13 +33,5 @@
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
@end

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6214" systemVersion="14A314h" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6207"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 gRPC. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Sample" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>

@ -1,13 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7702" systemVersion="14D131" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
@ -15,7 +16,38 @@
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BWr-eN-L3y">
<rect key="frame" x="16" y="20" width="568" height="150"/>
<constraints>
<constraint firstAttribute="width" constant="385" id="exg-IV-Kl0"/>
</constraints>
<string key="text">Sample app launch finished.
Check ViewController.m for the gRPC calls made, and the logs of this app for their results.
(You may need to make XCode's Debug Area visible).</string>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
<variation key="default">
<mask key="constraints">
<exclude reference="exg-IV-Kl0"/>
</mask>
</variation>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="BWr-eN-L3y" secondAttribute="bottom" constant="430" id="KFC-7p-hRl"/>
<constraint firstAttribute="trailing" secondItem="BWr-eN-L3y" secondAttribute="trailing" constant="16" id="M9C-nN-tFv"/>
<constraint firstItem="BWr-eN-L3y" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leadingMargin" id="SaP-0S-2LK"/>
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="BWr-eN-L3y" secondAttribute="bottom" id="wjC-O4-kJg"/>
<constraint firstItem="BWr-eN-L3y" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" id="ygF-6t-hrg"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="KFC-7p-hRl"/>
</mask>
</variation>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>

@ -23,7 +23,7 @@
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<string>Main</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>

@ -40,9 +40,6 @@
#import <RemoteTest/Messages.pbobjc.h>
#import <RemoteTest/Test.pbrpc.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {

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

@ -40,10 +40,13 @@
#import <gRPC/GRXWriteable.h>
#import <RemoteTest/Messages.pbobjc.h>
@interface RemoteTests : XCTestCase
// These are a few tests similar to InteropTests, but which use the generic gRPC client (GRPCCall)
// rather than a generated proto library on top of it.
@interface GRPCClientTests : XCTestCase
@end
@implementation RemoteTests
@implementation GRPCClientTests
- (void)testConnectionToRemoteServer {
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"Server reachable."];

@ -76,10 +76,10 @@
}
@end
@interface RemoteProtoTests : XCTestCase
@interface InteropTests : XCTestCase
@end
@implementation RemoteProtoTests {
@implementation InteropTests {
RMTTestService *_service;
}
@ -192,7 +192,7 @@
[expectation fulfill];
}
}];
[self waitForExpectationsWithTimeout:4 handler:nil];
}
@ -230,7 +230,7 @@
[requestsBuffer writesFinishedWithError:nil];
}
}
if (done) {
XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
[expectation fulfill];
@ -283,9 +283,9 @@
[requestsBuffer writeValue:request];
__block ProtoRPC *call = [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer
handler:^(BOOL done,
RMTStreamingOutputCallResponse *response,
NSError *error) {
handler:^(BOOL done,
RMTStreamingOutputCallResponse *response,
NSError *error) {
if (receivedResponse) {
XCTAssert(done, @"Unexpected extra response %@", response);
XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);

@ -41,13 +41,14 @@
#import <Route_guide/RouteGuide.pbobjc.h>
#import <Route_guide/RouteGuide.pbrpc.h>
@interface SampleTests : XCTestCase
// These tests require the gRPC-Java "RouteGuide" sample server to be running locally. To do so,
// install Gradle by following the instructions here: https://docs.gradle.org/current/userguide/installation.html
// And use it to run the server by following the instructions here: https://github.com/grpc/grpc-java/tree/master/examples
@interface LocalClearTextTests : XCTestCase
@end
// These tests require the gRPC-Java "RouteGuide" sample server to be running locally. Install the
// gRPC-Java library following the instructions here: https://github.com/grpc/grpc-java And run the
// server by following the instructions here: https://github.com/grpc/grpc-java/tree/master/examples
@implementation SampleTests
@implementation LocalClearTextTests
- (void)testConnectionToLocalServer {
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"Server reachable."];

@ -1,7 +1,10 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'gRPC/RxLibrary', :path => "../../.."
pod 'gRPC', :path => "../../.."
pod 'Protobuf', :git => 'https://github.com/google/protobuf.git'
pod 'RemoteTest', :path => "../generated_libraries/RemoteTestClient"
pod 'Route_guide', :path => "../generated_libraries/RouteGuideClient"
link_with 'AllTests'

@ -7,9 +7,12 @@
objects = {
/* Begin PBXBuildFile section */
6312AE4E1B1BF49B00341DEE /* GRPCClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */; };
63175DFF1B1B9FAF00027841 /* LocalClearTextTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63175DFE1B1B9FAF00027841 /* LocalClearTextTests.m */; };
63423F4A1B150A5F006CF63C /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; };
63423F511B151B77006CF63C /* RxLibraryUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */; };
635697CD1B14FC11007A7283 /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635697CC1B14FC11007A7283 /* Tests.m */; };
635ED2EC1B1A3BC400FDE5C3 /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; };
7D8A186224D39101F90230F6 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */; };
/* End PBXBuildFile section */
@ -38,11 +41,14 @@
/* Begin PBXFileReference section */
0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GRPCClientTests.m; sourceTree = "<group>"; };
63175DFE1B1B9FAF00027841 /* LocalClearTextTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalClearTextTests.m; sourceTree = "<group>"; };
63423F441B150A5F006CF63C /* AllTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AllTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
63423F501B151B77006CF63C /* RxLibraryUnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RxLibraryUnitTests.m; sourceTree = "<group>"; };
635697C71B14FC11007A7283 /* libTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTests.a; sourceTree = BUILT_PRODUCTS_DIR; };
635697CC1B14FC11007A7283 /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = "<group>"; };
635697D81B14FC11007A7283 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InteropTests.m; sourceTree = "<group>"; };
FF7B5489BCFE40111D768DD0 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -105,6 +111,9 @@
635697C91B14FC11007A7283 /* Tests */ = {
isa = PBXGroup;
children = (
6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */,
63175DFE1B1B9FAF00027841 /* LocalClearTextTests.m */,
635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */,
63423F501B151B77006CF63C /* RxLibraryUnitTests.m */,
635697CC1B14FC11007A7283 /* Tests.m */,
635697D71B14FC11007A7283 /* Supporting Files */,
@ -243,7 +252,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
63175DFF1B1B9FAF00027841 /* LocalClearTextTests.m in Sources */,
63423F511B151B77006CF63C /* RxLibraryUnitTests.m in Sources */,
6312AE4E1B1BF49B00341DEE /* GRPCClientTests.m in Sources */,
635ED2EC1B1A3BC400FDE5C3 /* InteropTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

@ -1,86 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <Python.h>
#include <grpc/grpc.h>
#include "grpc/_adapter/_completion_queue.h"
#include "grpc/_adapter/_channel.h"
#include "grpc/_adapter/_call.h"
#include "grpc/_adapter/_server.h"
#include "grpc/_adapter/_client_credentials.h"
#include "grpc/_adapter/_server_credentials.h"
static PyObject *init(PyObject *self) {
grpc_init();
Py_RETURN_NONE;
}
static PyObject *shutdown(PyObject *self) {
grpc_shutdown();
Py_RETURN_NONE;
}
static PyMethodDef _c_methods[] = {
{"init", (PyCFunction)init, METH_NOARGS,
"Initialize the module's static state."},
{"shut_down", (PyCFunction)shutdown, METH_NOARGS,
"Shut down the module's static state."},
{NULL},
};
PyMODINIT_FUNC init_c(void) {
PyObject *module;
module = Py_InitModule3("_c", _c_methods,
"Wrappings of C structures and functions.");
if (pygrpc_add_completion_queue(module) == -1) {
return;
}
if (pygrpc_add_channel(module) == -1) {
return;
}
if (pygrpc_add_call(module) == -1) {
return;
}
if (pygrpc_add_server(module) == -1) {
return;
}
if (pygrpc_add_client_credentials(module) == -1) {
return;
}
if (pygrpc_add_server_credentials(module) == -1) {
return;
}
}

@ -0,0 +1,61 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdlib.h>
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <grpc/grpc.h>
#include "grpc/_adapter/_c/types.h"
static PyMethodDef c_methods[] = {
{NULL}
};
PyMODINIT_FUNC init_c(void) {
PyObject *module;
module = Py_InitModule3("_c", c_methods,
"Wrappings of C structures and functions.");
if (pygrpc_module_add_types(module) < 0) {
return;
}
/* GRPC maintains an internal counter of how many times it has been
initialized and handles multiple pairs of grpc_init()/grpc_shutdown()
invocations accordingly. */
grpc_init();
atexit(&grpc_shutdown);
}

@ -0,0 +1,60 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "grpc/_adapter/_c/types.h"
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <grpc/grpc.h>
int pygrpc_module_add_types(PyObject *module) {
int i;
PyTypeObject *types[] = {
&pygrpc_ClientCredentials_type,
&pygrpc_ServerCredentials_type,
&pygrpc_CompletionQueue_type,
&pygrpc_Call_type,
&pygrpc_Channel_type,
&pygrpc_Server_type
};
for (i = 0; i < sizeof(types)/sizeof(PyTypeObject *); ++i) {
if (PyType_Ready(types[i]) < 0) {
return -1;
}
}
for (i = 0; i < sizeof(types)/sizeof(PyTypeObject *); ++i) {
Py_INCREF(types[i]);
PyModule_AddObject(module, types[i]->tp_name, (PyObject *)types[i]);
}
return 0;
}

@ -0,0 +1,271 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC__ADAPTER__C_TYPES_H_
#define GRPC__ADAPTER__C_TYPES_H_
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
/*=========================*/
/* Client-side credentials */
/*=========================*/
typedef struct ClientCredentials {
PyObject_HEAD
grpc_credentials *c_creds;
} ClientCredentials;
void pygrpc_ClientCredentials_dealloc(ClientCredentials *self);
ClientCredentials *pygrpc_ClientCredentials_google_default(
PyTypeObject *type, PyObject *ignored);
ClientCredentials *pygrpc_ClientCredentials_ssl(
PyTypeObject *type, PyObject *args, PyObject *kwargs);
ClientCredentials *pygrpc_ClientCredentials_composite(
PyTypeObject *type, PyObject *args, PyObject *kwargs);
ClientCredentials *pygrpc_ClientCredentials_compute_engine(
PyTypeObject *type, PyObject *ignored);
ClientCredentials *pygrpc_ClientCredentials_service_account(
PyTypeObject *type, PyObject *args, PyObject *kwargs);
ClientCredentials *pygrpc_ClientCredentials_jwt(
PyTypeObject *type, PyObject *args, PyObject *kwargs);
ClientCredentials *pygrpc_ClientCredentials_refresh_token(
PyTypeObject *type, PyObject *args, PyObject *kwargs);
ClientCredentials *pygrpc_ClientCredentials_fake_transport_security(
PyTypeObject *type, PyObject *ignored);
ClientCredentials *pygrpc_ClientCredentials_iam(
PyTypeObject *type, PyObject *args, PyObject *kwargs);
extern PyTypeObject pygrpc_ClientCredentials_type;
/*=========================*/
/* Server-side credentials */
/*=========================*/
typedef struct ServerCredentials {
PyObject_HEAD
grpc_server_credentials *c_creds;
} ServerCredentials;
void pygrpc_ServerCredentials_dealloc(ServerCredentials *self);
ServerCredentials *pygrpc_ServerCredentials_ssl(
PyTypeObject *type, PyObject *args, PyObject *kwargs);
ServerCredentials *pygrpc_ServerCredentials_fake_transport_security(
PyTypeObject *type, PyObject *ignored);
extern PyTypeObject pygrpc_ServerCredentials_type;
/*==================*/
/* Completion queue */
/*==================*/
typedef struct CompletionQueue {
PyObject_HEAD
grpc_completion_queue *c_cq;
} CompletionQueue;
CompletionQueue *pygrpc_CompletionQueue_new(
PyTypeObject *type, PyObject *args, PyObject *kwargs);
void pygrpc_CompletionQueue_dealloc(CompletionQueue *self);
PyObject *pygrpc_CompletionQueue_next(
CompletionQueue *self, PyObject *args, PyObject *kwargs);
PyObject *pygrpc_CompletionQueue_shutdown(
CompletionQueue *self, PyObject *ignored);
extern PyTypeObject pygrpc_CompletionQueue_type;
/*======*/
/* Call */
/*======*/
typedef struct Call {
PyObject_HEAD
grpc_call *c_call;
CompletionQueue *cq;
} Call;
Call *pygrpc_Call_new_empty(CompletionQueue *cq);
void pygrpc_Call_dealloc(Call *self);
PyObject *pygrpc_Call_start_batch(Call *self, PyObject *args, PyObject *kwargs);
PyObject *pygrpc_Call_cancel(Call *self, PyObject *args, PyObject *kwargs);
extern PyTypeObject pygrpc_Call_type;
/*=========*/
/* Channel */
/*=========*/
typedef struct Channel {
PyObject_HEAD
grpc_channel *c_chan;
} Channel;
Channel *pygrpc_Channel_new(
PyTypeObject *type, PyObject *args, PyObject *kwargs);
void pygrpc_Channel_dealloc(Channel *self);
Call *pygrpc_Channel_create_call(
Channel *self, PyObject *args, PyObject *kwargs);
extern PyTypeObject pygrpc_Channel_type;
/*========*/
/* Server */
/*========*/
typedef struct Server {
PyObject_HEAD
grpc_server *c_serv;
CompletionQueue *cq;
} Server;
Server *pygrpc_Server_new(PyTypeObject *type, PyObject *args, PyObject *kwargs);
void pygrpc_Server_dealloc(Server *self);
PyObject *pygrpc_Server_request_call(
Server *self, PyObject *args, PyObject *kwargs);
PyObject *pygrpc_Server_add_http2_port(
Server *self, PyObject *args, PyObject *kwargs);
PyObject *pygrpc_Server_start(Server *self, PyObject *ignored);
PyObject *pygrpc_Server_shutdown(
Server *self, PyObject *args, PyObject *kwargs);
extern PyTypeObject pygrpc_Server_type;
/*=========*/
/* Utility */
/*=========*/
/* Every tag that passes from Python GRPC to GRPC core is of this type. */
typedef struct pygrpc_tag {
PyObject *user_tag;
Call *call;
grpc_call_details request_call_details;
grpc_metadata_array request_metadata;
grpc_op *ops;
size_t nops;
int is_new_call;
} pygrpc_tag;
/* Construct a tag associated with a batch call. Does not take ownership of the
resources in the elements of ops. */
pygrpc_tag *pygrpc_produce_batch_tag(PyObject *user_tag, Call *call,
grpc_op *ops, size_t nops);
/* Construct a tag associated with a server request. The calling code should
use the appropriate fields of the produced tag in the invocation of
grpc_server_request_call. */
pygrpc_tag *pygrpc_produce_request_tag(PyObject *user_tag, Call *empty_call);
/* Construct a tag associated with a server shutdown. */
pygrpc_tag *pygrpc_produce_server_shutdown_tag(PyObject *user_tag);
/* Frees all resources owned by the tag and the tag itself. */
void pygrpc_discard_tag(pygrpc_tag *tag);
/* Consumes an event and its associated tag, providing a Python tuple of the
form `(type, tag, call, call_details, results)` (where type is an integer
corresponding to a grpc_completion_type, tag is an arbitrary PyObject, call
is the call object associated with the event [if any], call_details is a
tuple of form `(method, host, deadline)` [if such details are available],
and resultd is a list of tuples of form `(type, metadata, message, status,
cancelled)` [where type corresponds to a grpc_op_type, metadata is a
sequence of 2-sequences of strings, message is a byte string, and status is
a 2-tuple of an integer corresponding to grpc_status_code and a string of
status details]).
Frees all resources associated with the event tag. */
PyObject *pygrpc_consume_event(grpc_event event);
/* Transliterate the Python tuple of form `(type, metadata, message,
status)` (where type is an integer corresponding to a grpc_op_type, metadata
is a sequence of 2-sequences of strings, message is a byte string, and
status is 2-tuple of an integer corresponding to grpc_status_code and a
string of status details) to a grpc_op suitable for use in a
grpc_call_start_batch invocation. The grpc_op is a 'directory' of resources
that must be freed after GRPC core is done with them.
Calls gpr_malloc (or the appropriate type-specific grpc_*_create function)
to populate the appropriate union-discriminated members of the op.
Returns true on success, false on failure. */
int pygrpc_produce_op(PyObject *op, grpc_op *result);
/* Discards all resources associated with the passed in op that was produced by
pygrpc_produce_op. */
void pygrpc_discard_op(grpc_op op);
/* Transliterate the grpc_ops (which have been sent through a
grpc_call_start_batch invocation and whose corresponding event has appeared
on a completion queue) to a Python tuple of form `(type, metadata, message,
status, cancelled)` (where type is an integer corresponding to a
grpc_op_type, metadata is a sequence of 2-sequences of strings, message is a
byte string, and status is 2-tuple of an integer corresponding to
grpc_status_code and a string of status details).
Calls gpr_free (or the appropriate type-specific grpc_*_destroy function) on
the appropriate union-discriminated populated members of the ops. */
PyObject *pygrpc_consume_ops(grpc_op *op, size_t nops);
/* Transliterate from a gpr_timespec to a double (in units of seconds, either
from the epoch if interpreted absolutely or as a delta otherwise). */
double pygrpc_cast_gpr_timespec_to_double(gpr_timespec timespec);
/* Transliterate from a double (in units of seconds from the epoch if
interpreted absolutely or as a delta otherwise) to a gpr_timespec. */
gpr_timespec pygrpc_cast_double_to_gpr_timespec(double seconds);
/* Returns true on success, false on failure. */
int pygrpc_cast_pylist_to_send_metadata(
PyObject *pylist, grpc_metadata **metadata, size_t *count);
/* Returns a metadata array as a Python object on success, else NULL. */
PyObject *pygrpc_cast_metadata_array_to_pylist(grpc_metadata_array metadata);
/* Transliterate from a list of python channel arguments (2-tuples of string
and string|integer|None) to a grpc_channel_args object. The strings placed
in the grpc_channel_args object's grpc_arg elements are views of the Python
object. The Python object must live long enough for the grpc_channel_args
to be used. Arguments set to None are silently ignored. Returns true on
success, false on failure. */
int pygrpc_produce_channel_args(PyObject *py_args, grpc_channel_args *c_args);
void pygrpc_discard_channel_args(grpc_channel_args args);
/* Read the bytes from grpc_byte_buffer to a gpr_malloc'd array of bytes;
output to result and result_size. */
void pygrpc_byte_buffer_to_bytes(
grpc_byte_buffer *buffer, char **result, size_t *result_size);
/*========*/
/* Module */
/*========*/
/* Returns 0 on success, -1 on failure. */
int pygrpc_module_add_types(PyObject *module);
#endif /* GRPC__ADAPTER__C_TYPES_H_ */

@ -0,0 +1,163 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "grpc/_adapter/_c/types.h"
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
PyMethodDef pygrpc_Call_methods[] = {
{"start_batch", (PyCFunction)pygrpc_Call_start_batch, METH_KEYWORDS, ""},
{"cancel", (PyCFunction)pygrpc_Call_cancel, METH_KEYWORDS, ""},
{NULL}
};
const char pygrpc_Call_doc[] = "See grpc._adapter._types.Call.";
PyTypeObject pygrpc_Call_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"Call", /* tp_name */
sizeof(Call), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pygrpc_Call_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
pygrpc_Call_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
pygrpc_Call_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0 /* tp_new */
};
Call *pygrpc_Call_new_empty(CompletionQueue *cq) {
Call *call = (Call *)pygrpc_Call_type.tp_alloc(&pygrpc_Call_type, 0);
call->c_call = NULL;
call->cq = cq;
Py_XINCREF(call->cq);
return call;
}
void pygrpc_Call_dealloc(Call *self) {
if (self->c_call) {
grpc_call_destroy(self->c_call);
}
Py_XDECREF(self->cq);
self->ob_type->tp_free((PyObject *)self);
}
PyObject *pygrpc_Call_start_batch(Call *self, PyObject *args, PyObject *kwargs) {
PyObject *op_list;
PyObject *user_tag;
grpc_op *ops;
size_t nops;
size_t i;
size_t j;
pygrpc_tag *tag;
grpc_call_error errcode;
static char *keywords[] = {"ops", "tag", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO:start_batch", keywords,
&op_list, &user_tag)) {
return NULL;
}
if (!PyList_Check(op_list)) {
PyErr_SetString(PyExc_TypeError, "expected a list of OpArgs");
return NULL;
}
nops = PyList_Size(op_list);
ops = gpr_malloc(sizeof(grpc_op) * nops);
for (i = 0; i < nops; ++i) {
PyObject *item = PyList_GET_ITEM(op_list, i);
if (!pygrpc_produce_op(item, &ops[i])) {
for (j = 0; j < i; ++j) {
pygrpc_discard_op(ops[j]);
}
return NULL;
}
}
tag = pygrpc_produce_batch_tag(user_tag, self, ops, nops);
errcode = grpc_call_start_batch(self->c_call, tag->ops, tag->nops, tag);
gpr_free(ops);
return PyInt_FromLong(errcode);
}
PyObject *pygrpc_Call_cancel(Call *self, PyObject *args, PyObject *kwargs) {
PyObject *py_code = NULL;
grpc_call_error errcode;
int code;
char *details = NULL;
static char *keywords[] = {"code", "details", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Os:start_batch", keywords,
&py_code, &details)) {
return NULL;
}
if (py_code != NULL && details != NULL) {
if (!PyInt_Check(py_code)) {
PyErr_SetString(PyExc_TypeError, "expected integer code");
return NULL;
}
code = PyInt_AsLong(py_code);
errcode = grpc_call_cancel_with_status(self->c_call, code, details);
} else if (py_code != NULL || details != NULL) {
PyErr_SetString(PyExc_ValueError,
"if `code` is specified, so must `details`");
return NULL;
} else {
errcode = grpc_call_cancel(self->c_call);
}
return PyInt_FromLong(errcode);
}

@ -0,0 +1,134 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "grpc/_adapter/_c/types.h"
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <grpc/grpc.h>
PyMethodDef pygrpc_Channel_methods[] = {
{"create_call", (PyCFunction)pygrpc_Channel_create_call, METH_KEYWORDS, ""},
{NULL}
};
const char pygrpc_Channel_doc[] = "See grpc._adapter._types.Channel.";
PyTypeObject pygrpc_Channel_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"Channel", /* tp_name */
sizeof(Channel), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pygrpc_Channel_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
pygrpc_Channel_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
pygrpc_Channel_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
(newfunc)pygrpc_Channel_new /* tp_new */
};
Channel *pygrpc_Channel_new(
PyTypeObject *type, PyObject *args, PyObject *kwargs) {
Channel *self;
const char *target;
PyObject *py_args;
ClientCredentials *creds = NULL;
grpc_channel_args c_args;
char *keywords[] = {"target", "args", "creds", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|O!:Channel", keywords,
&target, &py_args, &pygrpc_ClientCredentials_type, &creds)) {
return NULL;
}
if (!pygrpc_produce_channel_args(py_args, &c_args)) {
return NULL;
}
self = (Channel *)type->tp_alloc(type, 0);
if (creds) {
self->c_chan = grpc_secure_channel_create(creds->c_creds, target, &c_args);
} else {
self->c_chan = grpc_channel_create(target, &c_args);
}
pygrpc_discard_channel_args(c_args);
return self;
}
void pygrpc_Channel_dealloc(Channel *self) {
grpc_channel_destroy(self->c_chan);
self->ob_type->tp_free((PyObject *)self);
}
Call *pygrpc_Channel_create_call(
Channel *self, PyObject *args, PyObject *kwargs) {
Call *call;
CompletionQueue *cq;
const char *method;
const char *host;
double deadline;
char *keywords[] = {"cq", "method", "host", "deadline", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!ssd:create_call", keywords,
&pygrpc_CompletionQueue_type, &cq, &method, &host, &deadline)) {
return NULL;
}
call = pygrpc_Call_new_empty(cq);
call->c_call = grpc_channel_create_call(
self->c_chan, cq->c_cq, method, host,
pygrpc_cast_double_to_gpr_timespec(deadline));
return call;
}

@ -0,0 +1,286 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "grpc/_adapter/_c/types.h"
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
PyMethodDef pygrpc_ClientCredentials_methods[] = {
{"google_default", (PyCFunction)pygrpc_ClientCredentials_google_default,
METH_CLASS|METH_NOARGS, ""},
{"ssl", (PyCFunction)pygrpc_ClientCredentials_ssl,
METH_CLASS|METH_KEYWORDS, ""},
{"composite", (PyCFunction)pygrpc_ClientCredentials_composite,
METH_CLASS|METH_KEYWORDS, ""},
{"compute_engine", (PyCFunction)pygrpc_ClientCredentials_compute_engine,
METH_CLASS|METH_NOARGS, ""},
{"service_account", (PyCFunction)pygrpc_ClientCredentials_service_account,
METH_CLASS|METH_KEYWORDS, ""},
{"jwt", (PyCFunction)pygrpc_ClientCredentials_jwt,
METH_CLASS|METH_KEYWORDS, ""},
{"refresh_token", (PyCFunction)pygrpc_ClientCredentials_refresh_token,
METH_CLASS|METH_KEYWORDS, ""},
{"fake_transport_security",
(PyCFunction)pygrpc_ClientCredentials_fake_transport_security,
METH_CLASS|METH_NOARGS, ""},
{"iam", (PyCFunction)pygrpc_ClientCredentials_iam,
METH_CLASS|METH_KEYWORDS, ""},
{NULL}
};
const char pygrpc_ClientCredentials_doc[] = "";
PyTypeObject pygrpc_ClientCredentials_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"ClientCredentials", /* tp_name */
sizeof(ClientCredentials), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pygrpc_ClientCredentials_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
pygrpc_ClientCredentials_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
pygrpc_ClientCredentials_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0 /* tp_new */
};
void pygrpc_ClientCredentials_dealloc(ClientCredentials *self) {
grpc_credentials_release(self->c_creds);
self->ob_type->tp_free((PyObject *)self);
}
ClientCredentials *pygrpc_ClientCredentials_google_default(
PyTypeObject *type, PyObject *ignored) {
ClientCredentials *self = (ClientCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_google_default_credentials_create();
if (!self->c_creds) {
Py_DECREF(self);
PyErr_SetString(PyExc_RuntimeError,
"couldn't create Google default credentials");
return NULL;
}
return self;
}
ClientCredentials *pygrpc_ClientCredentials_ssl(
PyTypeObject *type, PyObject *args, PyObject *kwargs) {
ClientCredentials *self;
const char *root_certs;
const char *private_key = NULL;
const char *cert_chain = NULL;
grpc_ssl_pem_key_cert_pair key_cert_pair;
static char *keywords[] = {"root_certs", "private_key", "cert_chain", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|zz:ssl", keywords,
&root_certs, &private_key, &cert_chain)) {
return NULL;
}
self = (ClientCredentials *)type->tp_alloc(type, 0);
if (private_key && cert_chain) {
key_cert_pair.private_key = private_key;
key_cert_pair.cert_chain = cert_chain;
self->c_creds = grpc_ssl_credentials_create(root_certs, &key_cert_pair);
} else {
self->c_creds = grpc_ssl_credentials_create(root_certs, NULL);
}
if (!self->c_creds) {
Py_DECREF(self);
PyErr_SetString(PyExc_RuntimeError, "couldn't create ssl credentials");
return NULL;
}
return self;
}
ClientCredentials *pygrpc_ClientCredentials_composite(
PyTypeObject *type, PyObject *args, PyObject *kwargs) {
ClientCredentials *self;
ClientCredentials *creds1;
ClientCredentials *creds2;
static char *keywords[] = {"creds1", "creds2", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O!:composite", keywords,
&pygrpc_ClientCredentials_type, &creds1,
&pygrpc_ClientCredentials_type, &creds2)) {
return NULL;
}
self = (ClientCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_composite_credentials_create(
creds1->c_creds, creds2->c_creds);
if (!self->c_creds) {
Py_DECREF(self);
PyErr_SetString(PyExc_RuntimeError, "couldn't create composite credentials");
return NULL;
}
return self;
}
ClientCredentials *pygrpc_ClientCredentials_compute_engine(
PyTypeObject *type, PyObject *ignored) {
ClientCredentials *self = (ClientCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_compute_engine_credentials_create();
if (!self->c_creds) {
Py_DECREF(self);
PyErr_SetString(PyExc_RuntimeError,
"couldn't create compute engine credentials");
return NULL;
}
return self;
}
ClientCredentials *pygrpc_ClientCredentials_service_account(
PyTypeObject *type, PyObject *args, PyObject *kwargs) {
ClientCredentials *self;
const char *json_key;
const char *scope;
double lifetime;
static char *keywords[] = {"json_key", "scope", "token_lifetime", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ssd:service_account", keywords,
&json_key, &scope, &lifetime)) {
return NULL;
}
self = (ClientCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_service_account_credentials_create(
json_key, scope, pygrpc_cast_double_to_gpr_timespec(lifetime));
if (!self->c_creds) {
Py_DECREF(self);
PyErr_SetString(PyExc_RuntimeError,
"couldn't create service account credentials");
return NULL;
}
return self;
}
ClientCredentials *pygrpc_ClientCredentials_jwt(
PyTypeObject *type, PyObject *args, PyObject *kwargs) {
ClientCredentials *self;
const char *json_key;
double lifetime;
static char *keywords[] = {"json_key", "token_lifetime", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sd:jwt", keywords,
&json_key, &lifetime)) {
return NULL;
}
self = (ClientCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_jwt_credentials_create(
json_key, pygrpc_cast_double_to_gpr_timespec(lifetime));
if (!self->c_creds) {
Py_DECREF(self);
PyErr_SetString(PyExc_RuntimeError, "couldn't create JWT credentials");
return NULL;
}
return self;
}
ClientCredentials *pygrpc_ClientCredentials_refresh_token(
PyTypeObject *type, PyObject *args, PyObject *kwargs) {
ClientCredentials *self;
const char *json_refresh_token;
static char *keywords[] = {"json_refresh_token", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:refresh_token", keywords,
&json_refresh_token)) {
return NULL;
}
self = (ClientCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_refresh_token_credentials_create(json_refresh_token);
if (!self->c_creds) {
Py_DECREF(self);
PyErr_SetString(PyExc_RuntimeError,
"couldn't create credentials from refresh token");
return NULL;
}
return self;
}
ClientCredentials *pygrpc_ClientCredentials_fake_transport_security(
PyTypeObject *type, PyObject *ignored) {
ClientCredentials *self = (ClientCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_fake_transport_security_credentials_create();
if (!self->c_creds) {
Py_DECREF(self);
PyErr_SetString(PyExc_RuntimeError,
"couldn't create fake credentials; "
"something is horribly wrong with the universe");
return NULL;
}
return self;
}
ClientCredentials *pygrpc_ClientCredentials_iam(
PyTypeObject *type, PyObject *args, PyObject *kwargs) {
ClientCredentials *self;
const char *authorization_token;
const char *authority_selector;
static char *keywords[] = {"authorization_token", "authority_selector", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss:iam", keywords,
&authorization_token, &authority_selector)) {
return NULL;
}
self = (ClientCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_iam_credentials_create(authorization_token,
authority_selector);
if (!self->c_creds) {
Py_DECREF(self);
PyErr_SetString(PyExc_RuntimeError, "couldn't create IAM credentials");
return NULL;
}
return self;
}

@ -0,0 +1,124 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "grpc/_adapter/_c/types.h"
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <grpc/grpc.h>
PyMethodDef pygrpc_CompletionQueue_methods[] = {
{"next", (PyCFunction)pygrpc_CompletionQueue_next, METH_KEYWORDS, ""},
{"shutdown", (PyCFunction)pygrpc_CompletionQueue_shutdown, METH_NOARGS, ""},
{NULL}
};
const char pygrpc_CompletionQueue_doc[] =
"See grpc._adapter._types.CompletionQueue.";
PyTypeObject pygrpc_CompletionQueue_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"CompletionQueue", /* tp_name */
sizeof(CompletionQueue), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pygrpc_CompletionQueue_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
pygrpc_CompletionQueue_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
pygrpc_CompletionQueue_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
(newfunc)pygrpc_CompletionQueue_new /* tp_new */
};
CompletionQueue *pygrpc_CompletionQueue_new(
PyTypeObject *type, PyObject *args, PyObject *kwargs) {
CompletionQueue *self = (CompletionQueue *)type->tp_alloc(type, 0);
self->c_cq = grpc_completion_queue_create();
return self;
}
void pygrpc_CompletionQueue_dealloc(CompletionQueue *self) {
grpc_completion_queue_destroy(self->c_cq);
self->ob_type->tp_free((PyObject *)self);
}
PyObject *pygrpc_CompletionQueue_next(
CompletionQueue *self, PyObject *args, PyObject *kwargs) {
double deadline;
grpc_event event;
PyObject *transliterated_event;
static char *keywords[] = {"deadline", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d:next", keywords,
&deadline)) {
return NULL;
}
Py_BEGIN_ALLOW_THREADS;
event = grpc_completion_queue_next(
self->c_cq, pygrpc_cast_double_to_gpr_timespec(deadline));
Py_END_ALLOW_THREADS;
transliterated_event = pygrpc_consume_event(event);
return transliterated_event;
}
PyObject *pygrpc_CompletionQueue_shutdown(
CompletionQueue *self, PyObject *ignored) {
grpc_completion_queue_shutdown(self->c_cq);
Py_RETURN_NONE;
}

@ -0,0 +1,183 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "grpc/_adapter/_c/types.h"
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <grpc/grpc.h>
PyMethodDef pygrpc_Server_methods[] = {
{"request_call", (PyCFunction)pygrpc_Server_request_call,
METH_KEYWORDS, ""},
{"add_http2_port", (PyCFunction)pygrpc_Server_add_http2_port,
METH_KEYWORDS, ""},
{"start", (PyCFunction)pygrpc_Server_start, METH_NOARGS, ""},
{"shutdown", (PyCFunction)pygrpc_Server_shutdown, METH_KEYWORDS, ""},
{NULL}
};
const char pygrpc_Server_doc[] = "See grpc._adapter._types.Server.";
PyTypeObject pygrpc_Server_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"Server", /* tp_name */
sizeof(Server), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pygrpc_Server_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
pygrpc_Server_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
pygrpc_Server_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
(newfunc)pygrpc_Server_new /* tp_new */
};
Server *pygrpc_Server_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
Server *self;
CompletionQueue *cq;
PyObject *py_args;
grpc_channel_args c_args;
char *keywords[] = {"cq", "args", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O:Channel", keywords,
&pygrpc_CompletionQueue_type, &cq, &py_args)) {
return NULL;
}
if (!pygrpc_produce_channel_args(py_args, &c_args)) {
return NULL;
}
self = (Server *)type->tp_alloc(type, 0);
self->c_serv = grpc_server_create(&c_args);
pygrpc_discard_channel_args(c_args);
self->cq = cq;
Py_INCREF(self->cq);
return self;
}
void pygrpc_Server_dealloc(Server *self) {
grpc_server_destroy(self->c_serv);
Py_XDECREF(self->cq);
self->ob_type->tp_free((PyObject *)self);
}
PyObject *pygrpc_Server_request_call(
Server *self, PyObject *args, PyObject *kwargs) {
CompletionQueue *cq;
PyObject *user_tag;
pygrpc_tag *tag;
Call *empty_call;
grpc_call_error errcode;
static char *keywords[] = {"cq", "tag", NULL};
if (!PyArg_ParseTupleAndKeywords(
args, kwargs, "O!O", keywords,
&pygrpc_CompletionQueue_type, &cq, &user_tag)) {
return NULL;
}
empty_call = pygrpc_Call_new_empty(cq);
tag = pygrpc_produce_request_tag(user_tag, empty_call);
errcode = grpc_server_request_call(
self->c_serv, &tag->call->c_call, &tag->request_call_details,
&tag->request_metadata, tag->call->cq->c_cq, self->cq->c_cq, tag);
Py_DECREF(empty_call);
return PyInt_FromLong(errcode);
}
PyObject *pygrpc_Server_add_http2_port(
Server *self, PyObject *args, PyObject *kwargs) {
const char *addr;
ServerCredentials *creds = NULL;
int port;
static char *keywords[] = {"addr", "creds", NULL};
if (!PyArg_ParseTupleAndKeywords(
args, kwargs, "s|O!:add_http2_port", keywords,
&addr, &pygrpc_ServerCredentials_type, &creds)) {
return NULL;
}
if (creds) {
port = grpc_server_add_secure_http2_port(
self->c_serv, addr, creds->c_creds);
} else {
port = grpc_server_add_http2_port(self->c_serv, addr);
}
return PyInt_FromLong(port);
}
PyObject *pygrpc_Server_start(Server *self, PyObject *ignored) {
grpc_server_start(self->c_serv);
Py_RETURN_NONE;
}
PyObject *pygrpc_Server_shutdown(
Server *self, PyObject *args, PyObject *kwargs) {
PyObject *user_tag = NULL;
pygrpc_tag *tag;
static char *keywords[] = {"tag", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", keywords, &user_tag)) {
return NULL;
}
if (user_tag) {
tag = pygrpc_produce_server_shutdown_tag(user_tag);
grpc_server_shutdown_and_notify(self->c_serv, tag);
} else {
grpc_server_shutdown(self->c_serv);
}
Py_RETURN_NONE;
}

@ -0,0 +1,146 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "grpc/_adapter/_c/types.h"
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
PyMethodDef pygrpc_ServerCredentials_methods[] = {
{"ssl", (PyCFunction)pygrpc_ServerCredentials_ssl,
METH_CLASS|METH_KEYWORDS, ""},
{"fake_transport_security",
(PyCFunction)pygrpc_ServerCredentials_fake_transport_security,
METH_CLASS|METH_NOARGS, ""},
{NULL}
};
const char pygrpc_ServerCredentials_doc[] = "";
PyTypeObject pygrpc_ServerCredentials_type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"ServerCredentials", /* tp_name */
sizeof(ServerCredentials), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pygrpc_ServerCredentials_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
pygrpc_ServerCredentials_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
pygrpc_ServerCredentials_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0 /* tp_new */
};
void pygrpc_ServerCredentials_dealloc(ServerCredentials *self) {
grpc_server_credentials_release(self->c_creds);
self->ob_type->tp_free((PyObject *)self);
}
ServerCredentials *pygrpc_ServerCredentials_ssl(
PyTypeObject *type, PyObject *args, PyObject *kwargs) {
ServerCredentials *self;
const char *root_certs;
PyObject *py_key_cert_pairs;
grpc_ssl_pem_key_cert_pair *key_cert_pairs;
size_t num_key_cert_pairs;
size_t i;
static char *keywords[] = {"root_certs", "key_cert_pairs", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zO:ssl", keywords,
&root_certs, &py_key_cert_pairs)) {
return NULL;
}
if (!PyList_Check(py_key_cert_pairs)) {
PyErr_SetString(PyExc_TypeError, "expected a list of 2-tuples of strings");
return NULL;
}
num_key_cert_pairs = PyList_Size(py_key_cert_pairs);
key_cert_pairs =
gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
for (i = 0; i < num_key_cert_pairs; ++i) {
PyObject *item = PyList_GET_ITEM(py_key_cert_pairs, i);
const char *key;
const char *cert;
if (!PyArg_ParseTuple(item, "zz", &key, &cert)) {
gpr_free(key_cert_pairs);
PyErr_SetString(PyExc_TypeError,
"expected a list of 2-tuples of strings");
return NULL;
}
key_cert_pairs[i].private_key = key;
key_cert_pairs[i].cert_chain = cert;
}
self = (ServerCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_ssl_server_credentials_create(
root_certs, key_cert_pairs, num_key_cert_pairs);
gpr_free(key_cert_pairs);
return self;
}
ServerCredentials *pygrpc_ServerCredentials_fake_transport_security(
PyTypeObject *type, PyObject *ignored) {
ServerCredentials *self = (ServerCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_fake_transport_security_server_credentials_create();
return self;
}

@ -0,0 +1,460 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <math.h>
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/slice.h>
#include <grpc/support/time.h>
#include "grpc/_adapter/_c/types.h"
pygrpc_tag *pygrpc_produce_batch_tag(
PyObject *user_tag, Call *call, grpc_op *ops, size_t nops) {
pygrpc_tag *tag = gpr_malloc(sizeof(pygrpc_tag));
tag->user_tag = user_tag;
Py_XINCREF(tag->user_tag);
tag->call = call;
Py_XINCREF(tag->call);
tag->ops = gpr_malloc(sizeof(grpc_op)*nops);
memcpy(tag->ops, ops, sizeof(grpc_op)*nops);
tag->nops = nops;
grpc_call_details_init(&tag->request_call_details);
grpc_metadata_array_init(&tag->request_metadata);
tag->is_new_call = 0;
return tag;
}
pygrpc_tag *pygrpc_produce_request_tag(PyObject *user_tag, Call *empty_call) {
pygrpc_tag *tag = gpr_malloc(sizeof(pygrpc_tag));
tag->user_tag = user_tag;
Py_XINCREF(tag->user_tag);
tag->call = empty_call;
Py_XINCREF(tag->call);
tag->ops = NULL;
tag->nops = 0;
grpc_call_details_init(&tag->request_call_details);
grpc_metadata_array_init(&tag->request_metadata);
tag->is_new_call = 1;
return tag;
}
pygrpc_tag *pygrpc_produce_server_shutdown_tag(PyObject *user_tag) {
pygrpc_tag *tag = gpr_malloc(sizeof(pygrpc_tag));
tag->user_tag = user_tag;
Py_XINCREF(tag->user_tag);
tag->call = NULL;
tag->ops = NULL;
tag->nops = 0;
grpc_call_details_init(&tag->request_call_details);
grpc_metadata_array_init(&tag->request_metadata);
tag->is_new_call = 0;
return tag;
}
void pygrpc_discard_tag(pygrpc_tag *tag) {
if (!tag) {
return;
}
Py_XDECREF(tag->user_tag);
Py_XDECREF(tag->call);
gpr_free(tag->ops);
grpc_call_details_destroy(&tag->request_call_details);
grpc_metadata_array_destroy(&tag->request_metadata);
gpr_free(tag);
}
PyObject *pygrpc_consume_event(grpc_event event) {
pygrpc_tag *tag;
PyObject *result;
if (event.type == GRPC_QUEUE_TIMEOUT) {
Py_RETURN_NONE;
}
tag = event.tag;
switch (event.type) {
case GRPC_QUEUE_SHUTDOWN:
result = Py_BuildValue("iOOOOO", GRPC_QUEUE_SHUTDOWN,
Py_None, Py_None, Py_None, Py_None, Py_True);
break;
case GRPC_OP_COMPLETE:
if (tag->is_new_call) {
result = Py_BuildValue(
"iOO(ssd)[(iNOOOO)]O", GRPC_OP_COMPLETE, tag->user_tag, tag->call,
tag->request_call_details.method, tag->request_call_details.host,
pygrpc_cast_gpr_timespec_to_double(tag->request_call_details.deadline),
GRPC_OP_RECV_INITIAL_METADATA,
pygrpc_cast_metadata_array_to_pylist(tag->request_metadata), Py_None,
Py_None, Py_None, Py_None,
event.success ? Py_True : Py_False);
} else {
result = Py_BuildValue("iOOONO", GRPC_OP_COMPLETE, tag->user_tag,
tag->call, Py_None, pygrpc_consume_ops(tag->ops, tag->nops),
event.success ? Py_True : Py_False);
}
break;
default:
PyErr_SetString(PyExc_ValueError,
"unknown completion type; could not translate event");
return NULL;
}
pygrpc_discard_tag(tag);
return result;
}
int pygrpc_produce_op(PyObject *op, grpc_op *result) {
static const int OP_TUPLE_SIZE = 5;
static const int STATUS_TUPLE_SIZE = 2;
static const int TYPE_INDEX = 0;
static const int INITIAL_METADATA_INDEX = 1;
static const int TRAILING_METADATA_INDEX = 2;
static const int MESSAGE_INDEX = 3;
static const int STATUS_INDEX = 4;
static const int STATUS_CODE_INDEX = 0;
static const int STATUS_DETAILS_INDEX = 1;
grpc_op c_op;
if (!PyTuple_Check(op)) {
PyErr_SetString(PyExc_TypeError, "expected tuple op");
return 0;
}
if (PyTuple_Size(op) != OP_TUPLE_SIZE) {
char buf[64];
snprintf(buf, sizeof(buf), "expected tuple op of length %d", OP_TUPLE_SIZE);
PyErr_SetString(PyExc_ValueError, buf);
return 0;
}
int type = PyInt_AsLong(PyTuple_GET_ITEM(op, TYPE_INDEX));
if (PyErr_Occurred()) {
return 0;
}
Py_ssize_t message_size;
char *message;
char *status_details;
gpr_slice message_slice;
c_op.op = type;
switch (type) {
case GRPC_OP_SEND_INITIAL_METADATA:
if (!pygrpc_cast_pylist_to_send_metadata(
PyTuple_GetItem(op, INITIAL_METADATA_INDEX),
&c_op.data.send_initial_metadata.metadata,
&c_op.data.send_initial_metadata.count)) {
return 0;
}
break;
case GRPC_OP_SEND_MESSAGE:
PyString_AsStringAndSize(
PyTuple_GET_ITEM(op, MESSAGE_INDEX), &message, &message_size);
message_slice = gpr_slice_from_copied_buffer(message, message_size);
c_op.data.send_message = grpc_byte_buffer_create(&message_slice, 1);
gpr_slice_unref(message_slice);
break;
case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
/* Don't need to fill in any other fields. */
break;
case GRPC_OP_SEND_STATUS_FROM_SERVER:
if (!pygrpc_cast_pylist_to_send_metadata(
PyTuple_GetItem(op, TRAILING_METADATA_INDEX),
&c_op.data.send_status_from_server.trailing_metadata,
&c_op.data.send_status_from_server.trailing_metadata_count)) {
return 0;
}
if (!PyTuple_Check(PyTuple_GET_ITEM(op, STATUS_INDEX))) {
char buf[64];
snprintf(buf, sizeof(buf), "expected tuple status in op of length %d",
STATUS_TUPLE_SIZE);
PyErr_SetString(PyExc_TypeError, buf);
return 0;
}
c_op.data.send_status_from_server.status = PyInt_AsLong(
PyTuple_GET_ITEM(PyTuple_GET_ITEM(op, STATUS_INDEX), STATUS_CODE_INDEX));
status_details = PyString_AsString(
PyTuple_GET_ITEM(PyTuple_GET_ITEM(op, STATUS_INDEX), STATUS_DETAILS_INDEX));
if (PyErr_Occurred()) {
return 0;
}
c_op.data.send_status_from_server.status_details =
gpr_malloc(strlen(status_details) + 1);
strcpy((char *)c_op.data.send_status_from_server.status_details,
status_details);
break;
case GRPC_OP_RECV_INITIAL_METADATA:
c_op.data.recv_initial_metadata = gpr_malloc(sizeof(grpc_metadata_array));
grpc_metadata_array_init(c_op.data.recv_initial_metadata);
break;
case GRPC_OP_RECV_MESSAGE:
c_op.data.recv_message = gpr_malloc(sizeof(grpc_byte_buffer *));
break;
case GRPC_OP_RECV_STATUS_ON_CLIENT:
c_op.data.recv_status_on_client.trailing_metadata =
gpr_malloc(sizeof(grpc_metadata_array));
grpc_metadata_array_init(c_op.data.recv_status_on_client.trailing_metadata);
c_op.data.recv_status_on_client.status =
gpr_malloc(sizeof(grpc_status_code *));
c_op.data.recv_status_on_client.status_details =
gpr_malloc(sizeof(char *));
*c_op.data.recv_status_on_client.status_details = NULL;
c_op.data.recv_status_on_client.status_details_capacity =
gpr_malloc(sizeof(size_t));
*c_op.data.recv_status_on_client.status_details_capacity = 0;
break;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
c_op.data.recv_close_on_server.cancelled = gpr_malloc(sizeof(int));
break;
default:
return 0;
}
*result = c_op;
return 1;
}
void pygrpc_discard_op(grpc_op op) {
switch(op.op) {
case GRPC_OP_SEND_INITIAL_METADATA:
gpr_free(op.data.send_initial_metadata.metadata);
break;
case GRPC_OP_SEND_MESSAGE:
grpc_byte_buffer_destroy(op.data.send_message);
break;
case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
/* Don't need to free any fields. */
break;
case GRPC_OP_SEND_STATUS_FROM_SERVER:
gpr_free(op.data.send_status_from_server.trailing_metadata);
gpr_free((char *)op.data.send_status_from_server.status_details);
break;
case GRPC_OP_RECV_INITIAL_METADATA:
grpc_metadata_array_destroy(op.data.recv_initial_metadata);
gpr_free(op.data.recv_initial_metadata);
break;
case GRPC_OP_RECV_MESSAGE:
grpc_byte_buffer_destroy(*op.data.recv_message);
gpr_free(op.data.recv_message);
break;
case GRPC_OP_RECV_STATUS_ON_CLIENT:
grpc_metadata_array_destroy(op.data.recv_status_on_client.trailing_metadata);
gpr_free(op.data.recv_status_on_client.trailing_metadata);
gpr_free(op.data.recv_status_on_client.status);
gpr_free(*op.data.recv_status_on_client.status_details);
gpr_free(op.data.recv_status_on_client.status_details);
gpr_free(op.data.recv_status_on_client.status_details_capacity);
break;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
gpr_free(op.data.recv_close_on_server.cancelled);
break;
}
}
PyObject *pygrpc_consume_ops(grpc_op *op, size_t nops) {
static const int TYPE_INDEX = 0;
static const int INITIAL_METADATA_INDEX = 1;
static const int TRAILING_METADATA_INDEX = 2;
static const int MESSAGE_INDEX = 3;
static const int STATUS_INDEX = 4;
static const int CANCELLED_INDEX = 5;
static const int OPRESULT_LENGTH = 6;
PyObject *list;
size_t i;
size_t j;
char *bytes;
size_t bytes_size;
PyObject *results = PyList_New(nops);
if (!results) {
return NULL;
}
for (i = 0; i < nops; ++i) {
PyObject *result = PyTuple_Pack(OPRESULT_LENGTH, Py_None, Py_None, Py_None,
Py_None, Py_None, Py_None);
PyTuple_SetItem(result, TYPE_INDEX, PyInt_FromLong(op[i].op));
switch(op[i].op) {
case GRPC_OP_RECV_INITIAL_METADATA:
PyTuple_SetItem(result, INITIAL_METADATA_INDEX,
list=PyList_New(op[i].data.recv_initial_metadata->count));
for (j = 0; j < op[i].data.recv_initial_metadata->count; ++j) {
grpc_metadata md = op[i].data.recv_initial_metadata->metadata[j];
PyList_SetItem(list, j, Py_BuildValue("ss#", md.key, md.value,
(Py_ssize_t)md.value_length));
}
break;
case GRPC_OP_RECV_MESSAGE:
if (*op[i].data.recv_message) {
pygrpc_byte_buffer_to_bytes(
*op[i].data.recv_message, &bytes, &bytes_size);
PyTuple_SetItem(result, MESSAGE_INDEX,
PyString_FromStringAndSize(bytes, bytes_size));
gpr_free(bytes);
} else {
PyTuple_SetItem(result, MESSAGE_INDEX, Py_BuildValue(""));
}
break;
case GRPC_OP_RECV_STATUS_ON_CLIENT:
PyTuple_SetItem(
result, TRAILING_METADATA_INDEX,
list = PyList_New(op[i].data.recv_status_on_client.trailing_metadata->count));
for (j = 0; j < op[i].data.recv_status_on_client.trailing_metadata->count; ++j) {
grpc_metadata md =
op[i].data.recv_status_on_client.trailing_metadata->metadata[j];
PyList_SetItem(list, j, Py_BuildValue("ss#", md.key, md.value,
(Py_ssize_t)md.value_length));
}
PyTuple_SetItem(
result, STATUS_INDEX, Py_BuildValue(
"is", *op[i].data.recv_status_on_client.status,
*op[i].data.recv_status_on_client.status_details));
break;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
PyTuple_SetItem(
result, CANCELLED_INDEX,
PyBool_FromLong(*op[i].data.recv_close_on_server.cancelled));
break;
default:
break;
}
pygrpc_discard_op(op[i]);
PyList_SetItem(results, i, result);
}
return results;
}
double pygrpc_cast_gpr_timespec_to_double(gpr_timespec timespec) {
return timespec.tv_sec + 1e-9*timespec.tv_nsec;
}
gpr_timespec pygrpc_cast_double_to_gpr_timespec(double seconds) {
gpr_timespec result;
if isinf(seconds) {
result = seconds > 0.0 ? gpr_inf_future : gpr_inf_past;
} else {
result.tv_sec = (time_t)seconds;
result.tv_nsec = ((seconds - result.tv_sec) * 1e9);
}
return result;
}
int pygrpc_produce_channel_args(PyObject *py_args, grpc_channel_args *c_args) {
size_t num_args = PyList_Size(py_args);
size_t i;
grpc_channel_args args = {num_args, gpr_malloc(sizeof(grpc_arg) * num_args)};
for (i = 0; i < args.num_args; ++i) {
char *key;
PyObject *value;
if (!PyArg_ParseTuple(PyList_GetItem(py_args, i), "zO", &key, &value)) {
gpr_free(args.args);
args.num_args = 0;
args.args = NULL;
PyErr_SetString(PyExc_TypeError,
"expected a list of 2-tuple of str and str|int|None");
return 0;
}
args.args[i].key = key;
if (PyInt_Check(value)) {
args.args[i].type = GRPC_ARG_INTEGER;
args.args[i].value.integer = PyInt_AsLong(value);
} else if (PyString_Check(value)) {
args.args[i].type = GRPC_ARG_STRING;
args.args[i].value.string = PyString_AsString(value);
} else if (value == Py_None) {
--args.num_args;
--i;
continue;
} else {
gpr_free(args.args);
args.num_args = 0;
args.args = NULL;
PyErr_SetString(PyExc_TypeError,
"expected a list of 2-tuple of str and str|int|None");
return 0;
}
}
*c_args = args;
return 1;
}
void pygrpc_discard_channel_args(grpc_channel_args args) {
gpr_free(args.args);
}
int pygrpc_cast_pylist_to_send_metadata(
PyObject *pylist, grpc_metadata **metadata, size_t *count) {
size_t i;
Py_ssize_t value_length;
*count = PyList_Size(pylist);
*metadata = gpr_malloc(sizeof(grpc_metadata) * *count);
for (i = 0; i < *count; ++i) {
if (!PyArg_ParseTuple(
PyList_GetItem(pylist, i), "ss#",
&(*metadata)[i].key, &(*metadata)[i].value, &value_length)) {
gpr_free(*metadata);
*count = 0;
*metadata = NULL;
return 0;
}
(*metadata)[i].value_length = value_length;
}
return 1;
}
PyObject *pygrpc_cast_metadata_array_to_pylist(grpc_metadata_array metadata) {
PyObject *result = PyList_New(metadata.count);
size_t i;
for (i = 0; i < metadata.count; ++i) {
PyList_SetItem(
result, i, Py_BuildValue(
"ss#", metadata.metadata[i].key, metadata.metadata[i].value,
(Py_ssize_t)metadata.metadata[i].value_length));
if (PyErr_Occurred()) {
Py_DECREF(result);
return NULL;
}
}
return result;
}
void pygrpc_byte_buffer_to_bytes(
grpc_byte_buffer *buffer, char **result, size_t *result_size) {
grpc_byte_buffer_reader *reader = grpc_byte_buffer_reader_create(buffer);
gpr_slice slice;
char *read_result = NULL;
size_t size = 0;
while (grpc_byte_buffer_reader_next(reader, &slice)) {
read_result = gpr_realloc(read_result, size + GPR_SLICE_LENGTH(slice));
memcpy(read_result + size, GPR_SLICE_START_PTR(slice),
GPR_SLICE_LENGTH(slice));
size = size + GPR_SLICE_LENGTH(slice);
gpr_slice_unref(slice);
}
grpc_byte_buffer_reader_destroy(reader);
*result_size = size;
*result = read_result;
}

@ -27,192 +27,40 @@
# (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 _adapter._c."""
import threading
import time
import unittest
from grpc._adapter import _c
from grpc._adapter import _datatypes
_TIMEOUT = 3
_FUTURE = time.time() + 60 * 60 * 24
_IDEMPOTENCE_DEMONSTRATION = 7
class _CTest(unittest.TestCase):
def testUpAndDown(self):
_c.init()
_c.shut_down()
def testCompletionQueue(self):
_c.init()
completion_queue = _c.CompletionQueue()
event = completion_queue.get(0)
self.assertIsNone(event)
event = completion_queue.get(time.time())
self.assertIsNone(event)
event = completion_queue.get(time.time() + _TIMEOUT)
self.assertIsNone(event)
completion_queue.stop()
for _ in range(_IDEMPOTENCE_DEMONSTRATION):
event = completion_queue.get(time.time() + _TIMEOUT)
self.assertIs(event.kind, _datatypes.Event.Kind.STOP)
del completion_queue
del event
from grpc._adapter import _types
_c.shut_down()
def testChannel(self):
_c.init()
channel = _c.Channel(
'test host:12345', None, server_host_override='ignored')
del channel
_c.shut_down()
def testCall(self):
method = 'test method'
host = 'test host'
_c.init()
channel = _c.Channel('%s:%d' % (host, 12345), None)
completion_queue = _c.CompletionQueue()
call = _c.Call(channel, completion_queue, method, host,
time.time() + _TIMEOUT)
del call
del completion_queue
del channel
class CTypeSmokeTest(unittest.TestCase):
_c.shut_down()
def testClientCredentialsUpDown(self):
credentials = _c.ClientCredentials.fake_transport_security()
del credentials
def testServer(self):
_c.init()
def testServerCredentialsUpDown(self):
credentials = _c.ServerCredentials.fake_transport_security()
del credentials
def testCompletionQueueUpDown(self):
completion_queue = _c.CompletionQueue()
server = _c.Server(completion_queue)
server.add_http2_addr('[::]:0')
server.start()
server.stop()
completion_queue.stop()
del server
del completion_queue
service_tag = object()
def testServerUpDown(self):
completion_queue = _c.CompletionQueue()
server = _c.Server(completion_queue)
server.add_http2_addr('[::]:0')
server.start()
server.service(service_tag)
server.stop()
completion_queue.stop()
event = completion_queue.get(time.time() + _TIMEOUT)
self.assertIs(event.kind, _datatypes.Event.Kind.SERVICE_ACCEPTED)
self.assertIs(event.tag, service_tag)
self.assertIsNone(event.service_acceptance)
for _ in range(_IDEMPOTENCE_DEMONSTRATION):
event = completion_queue.get(time.time() + _TIMEOUT)
self.assertIs(event.kind, _datatypes.Event.Kind.STOP)
del server
serv = _c.Server(completion_queue, [])
del serv
del completion_queue
completion_queue = _c.CompletionQueue()
server = _c.Server(completion_queue)
server.add_http2_addr('[::]:0')
server.start()
thread = threading.Thread(target=completion_queue.get, args=(_FUTURE,))
thread.start()
time.sleep(1)
server.stop()
completion_queue.stop()
for _ in range(_IDEMPOTENCE_DEMONSTRATION):
event = completion_queue.get(time.time() + _TIMEOUT)
self.assertIs(event.kind, _datatypes.Event.Kind.STOP)
thread.join()
del server
del completion_queue
_c.shut_down()
def test_client_credentials(self):
root_certificates = b'Trust starts here. Really.'
private_key = b'This is a really bad private key, yo.'
certificate_chain = b'Trust me! Do I not look trustworty?'
_c.init()
client_credentials = _c.ClientCredentials(
None, None, None)
self.assertIsNotNone(client_credentials)
client_credentials = _c.ClientCredentials(
root_certificates, None, None)
self.assertIsNotNone(client_credentials)
client_credentials = _c.ClientCredentials(
None, private_key, certificate_chain)
self.assertIsNotNone(client_credentials)
client_credentials = _c.ClientCredentials(
root_certificates, private_key, certificate_chain)
self.assertIsNotNone(client_credentials)
del client_credentials
_c.shut_down()
def test_server_credentials(self):
root_certificates = b'Trust starts here. Really.'
first_private_key = b'This is a really bad private key, yo.'
first_certificate_chain = b'Trust me! Do I not look trustworty?'
second_private_key = b'This is another bad private key, yo.'
second_certificate_chain = b'Look into my eyes; you can totes trust me.'
_c.init()
server_credentials = _c.ServerCredentials(
None, ((first_private_key, first_certificate_chain),))
del server_credentials
server_credentials = _c.ServerCredentials(
root_certificates, ((first_private_key, first_certificate_chain),))
del server_credentials
server_credentials = _c.ServerCredentials(
root_certificates,
((first_private_key, first_certificate_chain),
(second_private_key, second_certificate_chain),))
del server_credentials
with self.assertRaises(TypeError):
_c.ServerCredentials(
root_certificates, first_private_key, second_certificate_chain)
_c.shut_down()
@unittest.skip('TODO(nathaniel): find and use real-enough test credentials')
def test_secure_server(self):
_c.init()
server_credentials = _c.ServerCredentials(
'root certificate', (('private key', 'certificate chain'),))
completion_queue = _c.CompletionQueue()
server = _c.Server(completion_queue, server_credentials)
server.add_http2_addr('[::]:0')
server.start()
thread = threading.Thread(target=completion_queue.get, args=(_FUTURE,))
thread.start()
time.sleep(1)
server.stop()
completion_queue.stop()
for _ in range(_IDEMPOTENCE_DEMONSTRATION):
event = completion_queue.get(time.time() + _TIMEOUT)
self.assertIs(event.kind, _datatypes.Event.Kind.STOP)
thread.join()
del server
del completion_queue
def testChannelUpDown(self):
channel = _c.Channel('[::]:0', [])
del channel
_c.shut_down()
def testSecureChannelUpDown(self):
channel = _c.Channel('[::]:0', [], _c.ClientCredentials.fake_transport_security())
del channel
if __name__ == '__main__':

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save