From 7ac6bf07a90ce8921c3b24aa69644c9d581cfeea Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 25 Feb 2016 12:54:59 -0800 Subject: Finish porting rough implementation of poll() event strategy --- src/python/grpcio/grpc_core_dependencies.py | 1 + 1 file changed, 1 insertion(+) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 46b748ef36..2629b82aff 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -114,6 +114,7 @@ CORE_SOURCE_FILES = [ 'src/core/iomgr/endpoint_pair_posix.c', 'src/core/iomgr/endpoint_pair_windows.c', 'src/core/iomgr/ev_poll_and_epoll_posix.c', + 'src/core/iomgr/ev_poll_posix.c', 'src/core/iomgr/ev_posix.c', 'src/core/iomgr/exec_ctx.c', 'src/core/iomgr/executor.c', -- cgit v1.2.3 From e73e9e1a98600dfbf405c9bcbbfdcd4bd05d78f4 Mon Sep 17 00:00:00 2001 From: Christian Svensson Date: Thu, 10 Mar 2016 17:04:11 +0100 Subject: Allow directly specifiying connection path Make insecure_channel / secure_channel accept port=None and only use the 'host' argument. This enables using UNIX sockets without mangling the path of the socket. Signed-off-by: Christian Svensson --- src/python/grpcio/grpc/beta/implementations.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/grpc/beta/implementations.py b/src/python/grpcio/grpc/beta/implementations.py index a0ca330d2c..6f1ca2bb5e 100644 --- a/src/python/grpcio/grpc/beta/implementations.py +++ b/src/python/grpcio/grpc/beta/implementations.py @@ -1,4 +1,4 @@ -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -187,12 +187,13 @@ def insecure_channel(host, port): Args: host: The name of the remote host to which to connect. port: The port of the remote host to which to connect. + If None only the 'host' part will be used. Returns: A Channel to the remote host through which RPCs may be conducted. """ intermediary_low_channel = _intermediary_low.Channel( - '%s:%d' % (host, port), None) + '%s:%d' % (host, port) if port else host, None) return Channel(intermediary_low_channel._internal, intermediary_low_channel) # pylint: disable=protected-access @@ -202,13 +203,15 @@ def secure_channel(host, port, channel_credentials): Args: host: The name of the remote host to which to connect. port: The port of the remote host to which to connect. + If None only the 'host' part will be used. channel_credentials: A ChannelCredentials. Returns: A secure Channel to the remote host through which RPCs may be conducted. """ intermediary_low_channel = _intermediary_low.Channel( - '%s:%d' % (host, port), channel_credentials._low_credentials) + '%s:%d' % (host, port) if port else host, + channel_credentials._low_credentials) return Channel(intermediary_low_channel._internal, intermediary_low_channel) # pylint: disable=protected-access -- cgit v1.2.3 From c4b18a50de3ab04b189c9f0e2b56cb08a9f15542 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Fri, 15 Apr 2016 04:53:54 +0200 Subject: Adding support for msys. --- BUILD | 4 ++ Makefile | 2 + binding.gyp | 2 + build.yaml | 2 + config.m4 | 2 + gRPC.podspec | 2 + grpc.gemspec | 2 + include/grpc/impl/codegen/port_platform.h | 44 +++++++------- package.xml | 2 + src/core/lib/iomgr/tcp_server_windows.c | 27 +++------ src/core/lib/iomgr/tcp_windows.c | 14 ++++- src/core/lib/support/env_win32.c | 44 ++++++++------ src/core/lib/support/log_linux.c | 4 +- src/core/lib/support/log_win32.c | 18 +----- src/core/lib/support/string_util_win32.c | 91 +++++++++++++++++++++++++++++ src/core/lib/support/string_win32.c | 41 ++++--------- src/core/lib/support/time_win32.c | 4 +- src/core/lib/support/tmpfile_msys.c | 75 ++++++++++++++++++++++++ src/core/lib/support/tmpfile_posix.c | 4 +- src/core/lib/support/tmpfile_win32.c | 4 +- src/python/grpcio/grpc_core_dependencies.py | 2 + test/core/util/port_windows.c | 9 ++- test/core/util/test_config.c | 2 +- tools/doxygen/Doxyfile.core.internal | 2 + tools/run_tests/sources_and_headers.json | 2 + vsprojects/vcxproj/gpr/gpr.vcxproj | 4 ++ vsprojects/vcxproj/gpr/gpr.vcxproj.filters | 6 ++ 27 files changed, 296 insertions(+), 119 deletions(-) create mode 100644 src/core/lib/support/string_util_win32.c create mode 100644 src/core/lib/support/tmpfile_msys.c (limited to 'src/python/grpcio') diff --git a/BUILD b/BUILD index fa9a120989..237322a5e1 100644 --- a/BUILD +++ b/BUILD @@ -84,6 +84,7 @@ cc_library( "src/core/lib/support/stack_lockfree.c", "src/core/lib/support/string.c", "src/core/lib/support/string_posix.c", + "src/core/lib/support/string_util_win32.c", "src/core/lib/support/string_win32.c", "src/core/lib/support/subprocess_posix.c", "src/core/lib/support/subprocess_windows.c", @@ -98,6 +99,7 @@ cc_library( "src/core/lib/support/time_precise.c", "src/core/lib/support/time_win32.c", "src/core/lib/support/tls_pthread.c", + "src/core/lib/support/tmpfile_msys.c", "src/core/lib/support/tmpfile_posix.c", "src/core/lib/support/tmpfile_win32.c", "src/core/lib/support/wrap_memcpy.c", @@ -1211,6 +1213,7 @@ objc_library( "src/core/lib/support/stack_lockfree.c", "src/core/lib/support/string.c", "src/core/lib/support/string_posix.c", + "src/core/lib/support/string_util_win32.c", "src/core/lib/support/string_win32.c", "src/core/lib/support/subprocess_posix.c", "src/core/lib/support/subprocess_windows.c", @@ -1225,6 +1228,7 @@ objc_library( "src/core/lib/support/time_precise.c", "src/core/lib/support/time_win32.c", "src/core/lib/support/tls_pthread.c", + "src/core/lib/support/tmpfile_msys.c", "src/core/lib/support/tmpfile_posix.c", "src/core/lib/support/tmpfile_win32.c", "src/core/lib/support/wrap_memcpy.c", diff --git a/Makefile b/Makefile index 488d6f4dce..fdc523907d 100644 --- a/Makefile +++ b/Makefile @@ -2322,6 +2322,7 @@ LIBGPR_SRC = \ src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ + src/core/lib/support/string_util_win32.c \ src/core/lib/support/string_win32.c \ src/core/lib/support/subprocess_posix.c \ src/core/lib/support/subprocess_windows.c \ @@ -2336,6 +2337,7 @@ LIBGPR_SRC = \ src/core/lib/support/time_precise.c \ src/core/lib/support/time_win32.c \ src/core/lib/support/tls_pthread.c \ + src/core/lib/support/tmpfile_msys.c \ src/core/lib/support/tmpfile_posix.c \ src/core/lib/support/tmpfile_win32.c \ src/core/lib/support/wrap_memcpy.c \ diff --git a/binding.gyp b/binding.gyp index 8efc8a2b8e..492b75f8fd 100644 --- a/binding.gyp +++ b/binding.gyp @@ -519,6 +519,7 @@ 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', + 'src/core/lib/support/string_util_win32.c', 'src/core/lib/support/string_win32.c', 'src/core/lib/support/subprocess_posix.c', 'src/core/lib/support/subprocess_windows.c', @@ -533,6 +534,7 @@ 'src/core/lib/support/time_precise.c', 'src/core/lib/support/time_win32.c', 'src/core/lib/support/tls_pthread.c', + 'src/core/lib/support/tmpfile_msys.c', 'src/core/lib/support/tmpfile_posix.c', 'src/core/lib/support/tmpfile_win32.c', 'src/core/lib/support/wrap_memcpy.c', diff --git a/build.yaml b/build.yaml index a6feea5074..4a0663452d 100644 --- a/build.yaml +++ b/build.yaml @@ -103,6 +103,7 @@ filegroups: - src/core/lib/support/stack_lockfree.c - src/core/lib/support/string.c - src/core/lib/support/string_posix.c + - src/core/lib/support/string_util_win32.c - src/core/lib/support/string_win32.c - src/core/lib/support/subprocess_posix.c - src/core/lib/support/subprocess_windows.c @@ -117,6 +118,7 @@ filegroups: - src/core/lib/support/time_precise.c - src/core/lib/support/time_win32.c - src/core/lib/support/tls_pthread.c + - src/core/lib/support/tmpfile_msys.c - src/core/lib/support/tmpfile_posix.c - src/core/lib/support/tmpfile_win32.c - src/core/lib/support/wrap_memcpy.c diff --git a/config.m4 b/config.m4 index 7d3d899a40..acd798741f 100644 --- a/config.m4 +++ b/config.m4 @@ -63,6 +63,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ + src/core/lib/support/string_util_win32.c \ src/core/lib/support/string_win32.c \ src/core/lib/support/subprocess_posix.c \ src/core/lib/support/subprocess_windows.c \ @@ -77,6 +78,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/support/time_precise.c \ src/core/lib/support/time_win32.c \ src/core/lib/support/tls_pthread.c \ + src/core/lib/support/tmpfile_msys.c \ src/core/lib/support/tmpfile_posix.c \ src/core/lib/support/tmpfile_win32.c \ src/core/lib/support/wrap_memcpy.c \ diff --git a/gRPC.podspec b/gRPC.podspec index 82c5eaac41..b3122dd272 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -144,6 +144,7 @@ Pod::Spec.new do |s| 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', + 'src/core/lib/support/string_util_win32.c', 'src/core/lib/support/string_win32.c', 'src/core/lib/support/subprocess_posix.c', 'src/core/lib/support/subprocess_windows.c', @@ -158,6 +159,7 @@ Pod::Spec.new do |s| 'src/core/lib/support/time_precise.c', 'src/core/lib/support/time_win32.c', 'src/core/lib/support/tls_pthread.c', + 'src/core/lib/support/tmpfile_msys.c', 'src/core/lib/support/tmpfile_posix.c', 'src/core/lib/support/tmpfile_win32.c', 'src/core/lib/support/wrap_memcpy.c', diff --git a/grpc.gemspec b/grpc.gemspec index b8cfc4e6c4..3e0677ebdc 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -128,6 +128,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/support/stack_lockfree.c ) s.files += %w( src/core/lib/support/string.c ) s.files += %w( src/core/lib/support/string_posix.c ) + s.files += %w( src/core/lib/support/string_util_win32.c ) s.files += %w( src/core/lib/support/string_win32.c ) s.files += %w( src/core/lib/support/subprocess_posix.c ) s.files += %w( src/core/lib/support/subprocess_windows.c ) @@ -142,6 +143,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/support/time_precise.c ) s.files += %w( src/core/lib/support/time_win32.c ) s.files += %w( src/core/lib/support/tls_pthread.c ) + s.files += %w( src/core/lib/support/tmpfile_msys.c ) s.files += %w( src/core/lib/support/tmpfile_posix.c ) s.files += %w( src/core/lib/support/tmpfile_win32.c ) s.files += %w( src/core/lib/support/wrap_memcpy.c ) diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index 3242f07599..bbcb4098e3 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -82,28 +82,31 @@ things. */ #if !defined(GPR_NO_AUTODETECT_PLATFORM) +#if defined(_WIN64) || defined(WIN64) || defined(_WIN32) || defined(WIN32) #if defined(_WIN64) || defined(WIN64) -#define GPR_PLATFORM_STRING "windows" -#define GPR_WIN32 1 #define GPR_ARCH_64 1 -#define GPR_GETPID_IN_PROCESS_H 1 -#define GPR_WINSOCK_SOCKET 1 -#define GPR_WINDOWS_SUBPROCESS 1 -#ifdef __GNUC__ -#define GPR_GCC_ATOMIC 1 -#define GPR_GCC_TLS 1 #else -#define GPR_WIN32_ATOMIC 1 -#define GPR_MSVC_TLS 1 +#define GPR_ARCH_32 1 #endif -#define GPR_WINDOWS_CRASH_HANDLER 1 -#elif defined(_WIN32) || defined(WIN32) #define GPR_PLATFORM_STRING "windows" -#define GPR_ARCH_32 1 #define GPR_WIN32 1 -#define GPR_GETPID_IN_PROCESS_H 1 #define GPR_WINSOCK_SOCKET 1 #define GPR_WINDOWS_SUBPROCESS 1 +#define GPR_WIN32_ENV +#ifdef __MSYS__ +#define GPR_GETPID_IN_UNISTD_H 1 +#define GPR_MSYS_TMPFILE +#define GPR_POSIX_LOG +#define GPR_POSIX_STRING +#define GPR_POSIX_TIME +#else +#define GPR_GETPID_IN_PROCESS_H 1 +#define GPR_WIN32_TMPFILE +#define GPR_WIN32_LOG +#define GPR_WINDOWS_CRASH_HANDLER 1 +#define GPR_WIN32_STRING +#define GPR_WIN32_TIME +#endif #ifdef __GNUC__ #define GPR_GCC_ATOMIC 1 #define GPR_GCC_TLS 1 @@ -111,7 +114,6 @@ #define GPR_WIN32_ATOMIC 1 #define GPR_MSVC_TLS 1 #endif -#define GPR_WINDOWS_CRASH_HANDLER 1 #elif defined(ANDROID) || defined(__ANDROID__) #define GPR_PLATFORM_STRING "android" #define GPR_ANDROID 1 @@ -126,7 +128,8 @@ #define GPR_POSIX_SOCKETADDR 1 #define GPR_POSIX_SOCKETUTILS 1 #define GPR_POSIX_ENV 1 -#define GPR_POSIX_FILE 1 +#define GPR_POSIX_TMPFILE 1 +#define GPR_POSIX_LOG #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 @@ -153,6 +156,7 @@ #define GPR_GCC_ATOMIC 1 #define GPR_GCC_TLS 1 #define GPR_LINUX 1 +#define GPR_LINUX_LOG #define GPR_LINUX_MULTIPOLL_WITH_EPOLL 1 #define GPR_POSIX_WAKEUP_FD 1 #define GPR_POSIX_SOCKET 1 @@ -175,7 +179,7 @@ #ifndef GPR_LINUX_SOCKETUTILS #define GPR_POSIX_SOCKETUTILS #endif -#define GPR_POSIX_FILE 1 +#define GPR_POSIX_TMPFILE 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 @@ -213,7 +217,7 @@ #define GPR_POSIX_SOCKETADDR 1 #define GPR_POSIX_SOCKETUTILS 1 #define GPR_POSIX_ENV 1 -#define GPR_POSIX_FILE 1 +#define GPR_POSIX_TMPFILE 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 @@ -243,7 +247,7 @@ #define GPR_POSIX_SOCKETADDR 1 #define GPR_POSIX_SOCKETUTILS 1 #define GPR_POSIX_ENV 1 -#define GPR_POSIX_FILE 1 +#define GPR_POSIX_TMPFILE 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 @@ -280,7 +284,7 @@ #define GPR_POSIX_SOCKETADDR 1 #define GPR_POSIX_SOCKETUTILS 1 #define GPR_POSIX_ENV 1 -#define GPR_POSIX_FILE 1 +#define GPR_POSIX_TMPFILE 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 diff --git a/package.xml b/package.xml index 2f4c625539..b21e974c8e 100644 --- a/package.xml +++ b/package.xml @@ -131,6 +131,7 @@ + @@ -145,6 +146,7 @@ + diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c index 6940dec7b0..53f58477a4 100644 --- a/src/core/lib/iomgr/tcp_server_windows.c +++ b/src/core/lib/iomgr/tcp_server_windows.c @@ -510,30 +510,17 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, unsigned port_index) { - grpc_tcp_listener *sp; - for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index) - ; - if (sp) { - return 1; - } else { - return 0; - } + (void)s; + (void)port_index; + abort(); } int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index, unsigned fd_index) { - grpc_tcp_listener *sp; - if (fd_index != 0) { - /* Windows implementation has only one fd per port_index. */ - return -1; - } - for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index) - ; - if (sp) { - return _open_osfhandle((intptr_t)sp->socket->socket, 0); - } else { - return -1; - } + (void)s; + (void)port_index; + (void)fd_index; + abort(); } void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, diff --git a/src/core/lib/iomgr/tcp_windows.c b/src/core/lib/iomgr/tcp_windows.c index 7ee689a7e4..3996823933 100644 --- a/src/core/lib/iomgr/tcp_windows.c +++ b/src/core/lib/iomgr/tcp_windows.c @@ -35,6 +35,8 @@ #ifdef GPR_WINSOCK_SOCKET +#include + #include "src/core/lib/iomgr/sockaddr_win32.h" #include @@ -51,12 +53,20 @@ #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/timer.h" +#if defined(__MSYS__) && defined(GPR_ARCH_64) +/* Nasty workaround for nasty bug when using the 64 bits msys compiler + in conjunction with Microsoft Windows headers. */ +#define GRPC_FIONBIO _IOW('f', 126, uint32_t) +#else +#define GRPC_FIONBIO FIONBIO +#endif + static int set_non_block(SOCKET sock) { int status; - unsigned long param = 1; + uint32_t param = 1; DWORD ret; status = - WSAIoctl(sock, FIONBIO, ¶m, sizeof(param), NULL, 0, &ret, NULL, NULL); + WSAIoctl(sock, GRPC_FIONBIO, ¶m, sizeof(param), NULL, 0, &ret, NULL, NULL); return status == 0; } diff --git a/src/core/lib/support/env_win32.c b/src/core/lib/support/env_win32.c index ef84c941df..e670e1e8d0 100644 --- a/src/core/lib/support/env_win32.c +++ b/src/core/lib/support/env_win32.c @@ -33,41 +33,47 @@ #include -#ifdef GPR_WIN32 +#ifdef GPR_WIN32_ENV + +#include #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" - -#ifdef __MINGW32__ -errno_t getenv_s(size_t *size_needed, char *buffer, size_t size, - const char *varname); -#else -#include -#endif +#include "src/core/lib/support/string_win32.h" #include #include #include char *gpr_getenv(const char *name) { - size_t size; char *result = NULL; - errno_t err; + DWORD size; + LPTSTR tresult = NULL; + LPTSTR tname = gpr_char_to_tchar(name); + DWORD ret; - err = getenv_s(&size, NULL, 0, name); - if (err || (size == 0)) return NULL; - result = gpr_malloc(size); - err = getenv_s(&size, result, size, name); - if (err) { - gpr_free(result); + ret = GetEnvironmentVariable(tname, NULL, 0); + if (ret == 0) return NULL; + size = ret * (DWORD)sizeof(TCHAR); + tresult = gpr_malloc(size); + ret = GetEnvironmentVariable(tname, tresult, size); + gpr_free(tname); + if (ret == 0) { + gpr_free(tresult); return NULL; } + result = gpr_tchar_to_char(tresult); + gpr_free(tresult); return result; } void gpr_setenv(const char *name, const char *value) { - errno_t res = _putenv_s(name, value); - GPR_ASSERT(res == 0); + LPTSTR tname = gpr_char_to_tchar(name); + LPTSTR tvalue = gpr_char_to_tchar(value); + BOOL res = SetEnvironmentVariable(tname, tvalue); + gpr_free(tname); + gpr_free(tvalue); + GPR_ASSERT(res); } -#endif /* GPR_WIN32 */ +#endif /* GPR_WIN32_ENV */ diff --git a/src/core/lib/support/log_linux.c b/src/core/lib/support/log_linux.c index ff3febb38e..ca04c022e3 100644 --- a/src/core/lib/support/log_linux.c +++ b/src/core/lib/support/log_linux.c @@ -41,7 +41,7 @@ #include -#ifdef GPR_LINUX +#ifdef GPR_LINUX_LOG #include #include @@ -103,4 +103,4 @@ void gpr_default_log(gpr_log_func_args *args) { gpr_free(prefix); } -#endif +#endif /* GPR_LINUX_LOG */ diff --git a/src/core/lib/support/log_win32.c b/src/core/lib/support/log_win32.c index ba78497a0a..29735bd18c 100644 --- a/src/core/lib/support/log_win32.c +++ b/src/core/lib/support/log_win32.c @@ -33,7 +33,7 @@ #include -#ifdef GPR_WIN32 +#ifdef GPR_WIN32_LOG #include #include @@ -109,18 +109,4 @@ void gpr_default_log(gpr_log_func_args *args) { fflush(stderr); } -char *gpr_format_message(int messageid) { - LPTSTR tmessage; - char *message; - DWORD status = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, (DWORD)messageid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)(&tmessage), 0, NULL); - if (status == 0) return gpr_strdup("Unable to retrieve error string"); - message = gpr_tchar_to_char(tmessage); - LocalFree(tmessage); - return message; -} - -#endif /* GPR_WIN32 */ +#endif /* GPR_WIN32_LOG */ diff --git a/src/core/lib/support/string_util_win32.c b/src/core/lib/support/string_util_win32.c new file mode 100644 index 0000000000..fd14ce54e4 --- /dev/null +++ b/src/core/lib/support/string_util_win32.c @@ -0,0 +1,91 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* Posix code for gpr snprintf support. */ + +#include + +#ifdef GPR_WIN32 + +#include +#include +#include +#include +#include + +#include +#include + +#include "src/core/lib/support/string.h" + +#if defined UNICODE || defined _UNICODE +LPTSTR +gpr_char_to_tchar(LPCSTR input) { + LPTSTR ret; + int needed = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0); + if (needed <= 0) return NULL; + ret = gpr_malloc((unsigned)needed * sizeof(TCHAR)); + MultiByteToWideChar(CP_UTF8, 0, input, -1, ret, needed); + return ret; +} + +LPSTR +gpr_tchar_to_char(LPCTSTR input) { + LPSTR ret; + int needed = WideCharToMultiByte(CP_UTF8, 0, input, -1, NULL, 0, NULL, NULL); + if (needed <= 0) return NULL; + ret = gpr_malloc((unsigned)needed); + WideCharToMultiByte(CP_UTF8, 0, input, -1, ret, needed, NULL, NULL); + return ret; +} +#else +char *gpr_tchar_to_char(LPTSTR input) { return gpr_strdup(input); } + +char *gpr_char_to_tchar(LPTSTR input) { return gpr_strdup(input); } +#endif + +char *gpr_format_message(int messageid) { + LPTSTR tmessage; + char *message; + DWORD status = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, (DWORD)messageid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)(&tmessage), 0, NULL); + if (status == 0) return gpr_strdup("Unable to retrieve error string"); + message = gpr_tchar_to_char(tmessage); + LocalFree(tmessage); + return message; +} + +#endif /* GPR_WIN32 */ diff --git a/src/core/lib/support/string_win32.c b/src/core/lib/support/string_win32.c index a2f9857356..8382cde15a 100644 --- a/src/core/lib/support/string_win32.c +++ b/src/core/lib/support/string_win32.c @@ -31,23 +31,28 @@ * */ -/* Posix code for gpr snprintf support. */ +/* Windows code for gpr snprintf support. */ #include -#ifdef GPR_WIN32 +#ifdef GPR_WIN32_STRING #include #include #include +#include +#include #include +#include #include "src/core/lib/support/string.h" int gpr_asprintf(char **strp, const char *format, ...) { va_list args; int ret; + + HRESULT success; size_t strp_buflen; /* Determine the length. */ @@ -68,9 +73,9 @@ int gpr_asprintf(char **strp, const char *format, ...) { /* Print to the buffer. */ va_start(args, format); - ret = vsnprintf_s(*strp, strp_buflen, _TRUNCATE, format, args); + success = StringCbVPrintfA(*strp, strp_buflen, format, args); va_end(args); - if ((size_t)ret == strp_buflen - 1) { + if (success == S_OK) { return ret; } @@ -80,30 +85,4 @@ int gpr_asprintf(char **strp, const char *format, ...) { return -1; } -#if defined UNICODE || defined _UNICODE -LPTSTR -gpr_char_to_tchar(LPCSTR input) { - LPTSTR ret; - int needed = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0); - if (needed <= 0) return NULL; - ret = gpr_malloc((unsigned)needed * sizeof(TCHAR)); - MultiByteToWideChar(CP_UTF8, 0, input, -1, ret, needed); - return ret; -} - -LPSTR -gpr_tchar_to_char(LPCTSTR input) { - LPSTR ret; - int needed = WideCharToMultiByte(CP_UTF8, 0, input, -1, NULL, 0, NULL, NULL); - if (needed <= 0) return NULL; - ret = gpr_malloc((unsigned)needed); - WideCharToMultiByte(CP_UTF8, 0, input, -1, ret, needed, NULL, NULL); - return ret; -} -#else -char *gpr_tchar_to_char(LPTSTR input) { return gpr_strdup(input); } - -char *gpr_char_to_tchar(LPTSTR input) { return gpr_strdup(input); } -#endif - -#endif /* GPR_WIN32 */ +#endif /* GPR_WIN32_STRING */ diff --git a/src/core/lib/support/time_win32.c b/src/core/lib/support/time_win32.c index f7acbd14a6..9e924ab3f4 100644 --- a/src/core/lib/support/time_win32.c +++ b/src/core/lib/support/time_win32.c @@ -35,7 +35,7 @@ #include -#ifdef GPR_WIN32 +#ifdef GPR_WIN32_TIME #include #include @@ -107,4 +107,4 @@ void gpr_sleep_until(gpr_timespec until) { } } -#endif /* GPR_WIN32 */ +#endif /* GPR_WIN32_TIME */ diff --git a/src/core/lib/support/tmpfile_msys.c b/src/core/lib/support/tmpfile_msys.c new file mode 100644 index 0000000000..f0f803aa75 --- /dev/null +++ b/src/core/lib/support/tmpfile_msys.c @@ -0,0 +1,75 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#ifdef GPR_MSYS_TMPFILE + +#include +#include +#include +#include + +#include +#include +#include + +#include "src/core/lib/support/string_win32.h" +#include "src/core/lib/support/tmpfile.h" + +FILE *gpr_tmpfile(const char *prefix, char **tmp_filename_out) { + FILE *result = NULL; + char tmp_filename[MAX_PATH]; + UINT success; + + if (tmp_filename_out != NULL) *tmp_filename_out = NULL; + + /* Generate a unique filename with our template + temporary path. */ + success = GetTempFileNameA(".", prefix, 0, tmp_filename); + fprintf(stderr, "success = %d\n", success); + if (!success) goto end; + + /* Open a file there. */ + result = fopen(tmp_filename, "wb+"); + fprintf(stderr, "result = %p\n", result); + if (result == NULL) goto end; + +end: + if (result && tmp_filename_out) { + *tmp_filename_out = gpr_strdup(tmp_filename); + } + + return result; +} + +#endif /* GPR_MSYS_TMPFILE */ diff --git a/src/core/lib/support/tmpfile_posix.c b/src/core/lib/support/tmpfile_posix.c index 9e0e7ad808..0cd4bb6fc3 100644 --- a/src/core/lib/support/tmpfile_posix.c +++ b/src/core/lib/support/tmpfile_posix.c @@ -33,7 +33,7 @@ #include -#ifdef GPR_POSIX_FILE +#ifdef GPR_POSIX_TMPFILE #include "src/core/lib/support/tmpfile.h" @@ -82,4 +82,4 @@ end: return result; } -#endif /* GPR_POSIX_FILE */ +#endif /* GPR_POSIX_TMPFILE */ diff --git a/src/core/lib/support/tmpfile_win32.c b/src/core/lib/support/tmpfile_win32.c index 0cb2904f8d..9ac73128c3 100644 --- a/src/core/lib/support/tmpfile_win32.c +++ b/src/core/lib/support/tmpfile_win32.c @@ -33,7 +33,7 @@ #include -#ifdef GPR_WIN32 +#ifdef GPR_WIN32_TMPFILE #include #include @@ -81,4 +81,4 @@ end: return result; } -#endif /* GPR_WIN32 */ +#endif /* GPR_WIN32_TMPFILE */ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 1f7f2a196b..e389782b47 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -57,6 +57,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', + 'src/core/lib/support/string_util_win32.c', 'src/core/lib/support/string_win32.c', 'src/core/lib/support/subprocess_posix.c', 'src/core/lib/support/subprocess_windows.c', @@ -71,6 +72,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/support/time_precise.c', 'src/core/lib/support/time_win32.c', 'src/core/lib/support/tls_pthread.c', + 'src/core/lib/support/tmpfile_msys.c', 'src/core/lib/support/tmpfile_posix.c', 'src/core/lib/support/tmpfile_win32.c', 'src/core/lib/support/wrap_memcpy.c', diff --git a/test/core/util/port_windows.c b/test/core/util/port_windows.c index 2b6d3dd223..154d607ec7 100644 --- a/test/core/util/port_windows.c +++ b/test/core/util/port_windows.c @@ -51,6 +51,11 @@ #include "src/core/lib/support/env.h" #include "test/core/util/port_server_client.h" +#if GPR_GETPID_IN_UNISTD_H +#include +static int _getpid() { return getpid(); } +#endif + #define NUM_RANDOM_PORTS_TO_PICK 100 static int *chosen_ports = NULL; @@ -114,7 +119,7 @@ static int is_port_available(int *port, int is_tcp) { /* Try binding to port */ addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(*port); + addr.sin_port = htons((u_short)*port); if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { gpr_log(GPR_DEBUG, "bind(port=%d) failed: %s", *port, strerror(errno)); closesocket(fd); @@ -127,7 +132,7 @@ static int is_port_available(int *port, int is_tcp) { closesocket(fd); return 0; } - GPR_ASSERT(alen <= sizeof(addr)); + GPR_ASSERT(alen <= (socklen_t)sizeof(addr)); actual_port = ntohs(addr.sin_port); GPR_ASSERT(actual_port > 0); if (*port == 0) { diff --git a/test/core/util/test_config.c b/test/core/util/test_config.c index 3155a4ece6..62468a5a61 100644 --- a/test/core/util/test_config.c +++ b/test/core/util/test_config.c @@ -50,7 +50,7 @@ static unsigned seed(void) { return (unsigned)getpid(); } #if GPR_GETPID_IN_PROCESS_H #include -static unsigned seed(void) { return _getpid(); } +static unsigned seed(void) { return (unsigned)_getpid(); } #endif #if GPR_WINDOWS_CRASH_HANDLER diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index b131a55b59..e0d9714828 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1167,6 +1167,7 @@ src/core/lib/support/slice_buffer.c \ src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ +src/core/lib/support/string_util_win32.c \ src/core/lib/support/string_win32.c \ src/core/lib/support/subprocess_posix.c \ src/core/lib/support/subprocess_windows.c \ @@ -1181,6 +1182,7 @@ src/core/lib/support/time_posix.c \ src/core/lib/support/time_precise.c \ src/core/lib/support/time_win32.c \ src/core/lib/support/tls_pthread.c \ +src/core/lib/support/tmpfile_msys.c \ src/core/lib/support/tmpfile_posix.c \ src/core/lib/support/tmpfile_win32.c \ src/core/lib/support/wrap_memcpy.c diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 0b68315c82..b9a004423c 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -5429,6 +5429,7 @@ "src/core/lib/support/string.c", "src/core/lib/support/string.h", "src/core/lib/support/string_posix.c", + "src/core/lib/support/string_util_win32.c", "src/core/lib/support/string_win32.c", "src/core/lib/support/string_win32.h", "src/core/lib/support/subprocess_posix.c", @@ -5447,6 +5448,7 @@ "src/core/lib/support/time_win32.c", "src/core/lib/support/tls_pthread.c", "src/core/lib/support/tmpfile.h", + "src/core/lib/support/tmpfile_msys.c", "src/core/lib/support/tmpfile_posix.c", "src/core/lib/support/tmpfile_win32.c", "src/core/lib/support/wrap_memcpy.c" diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index cdb128e48e..26195bb541 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -259,6 +259,8 @@ + + @@ -287,6 +289,8 @@ + + diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index 8af6fdd44c..be15391b09 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -82,6 +82,9 @@ src\core\lib\support + + src\core\lib\support + src\core\lib\support @@ -124,6 +127,9 @@ src\core\lib\support + + src\core\lib\support + src\core\lib\support -- cgit v1.2.3 From 2e7d957a63c9bcfe0235f8b5d55fd9a372a32ced Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Fri, 15 Apr 2016 17:29:57 -0700 Subject: Provide a function that converts grpc_call_error values into a string --- grpc.def | 1 + include/grpc/grpc.h | 3 ++ src/core/lib/surface/call.c | 37 ++++++++++++++++++++++ src/python/grpcio/grpc/_cython/imports.generated.c | 2 ++ src/python/grpcio/grpc/_cython/imports.generated.h | 3 ++ src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 ++ src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 ++ 7 files changed, 51 insertions(+) (limited to 'src/python/grpcio') diff --git a/grpc.def b/grpc.def index f81aa1b05a..5e2de0ad2a 100644 --- a/grpc.def +++ b/grpc.def @@ -86,6 +86,7 @@ EXPORTS grpc_header_key_is_legal grpc_header_nonbin_value_is_legal grpc_is_binary_header + grpc_call_error_to_string grpc_auth_property_iterator_next grpc_auth_context_property_iterator grpc_auth_context_peer_identity diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 5c868aece3..0ca28c0fef 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -384,6 +384,9 @@ GRPCAPI int grpc_header_nonbin_value_is_legal(const char *value, size_t length); /** Check whether a metadata key corresponds to a binary value */ GRPCAPI int grpc_is_binary_header(const char *key, size_t length); +/** Convert grpc_call_error values to a string */ +GRPCAPI const char *grpc_call_error_to_string(grpc_call_error error); + #ifdef __cplusplus } #endif diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 6581bbd3d1..8deb3442de 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -1512,3 +1512,40 @@ grpc_compression_algorithm grpc_call_compression_for_level( gpr_mu_unlock(&call->mu); return grpc_compression_algorithm_for_level(level, accepted_encodings); } + +const char *grpc_call_error_to_string(grpc_call_error error) { + switch (error) { + case GRPC_CALL_ERROR: + return "GRPC_CALL_ERROR"; + case GRPC_CALL_ERROR_ALREADY_ACCEPTED: + return "GRPC_CALL_ERROR_ALREADY_ACCEPTED"; + case GRPC_CALL_ERROR_ALREADY_FINISHED: + return "GRPC_CALL_ERROR_ALREADY_FINISHED"; + case GRPC_CALL_ERROR_ALREADY_INVOKED: + return "GRPC_CALL_ERROR_ALREADY_INVOKED"; + case GRPC_CALL_ERROR_BATCH_TOO_BIG: + return "GRPC_CALL_ERROR_BATCH_TOO_BIG"; + case GRPC_CALL_ERROR_INVALID_FLAGS: + return "GRPC_CALL_ERROR_INVALID_FLAGS"; + case GRPC_CALL_ERROR_INVALID_MESSAGE: + return "GRPC_CALL_ERROR_INVALID_MESSAGE"; + case GRPC_CALL_ERROR_INVALID_METADATA: + return "GRPC_CALL_ERROR_INVALID_METADATA"; + case GRPC_CALL_ERROR_NOT_INVOKED: + return "GRPC_CALL_ERROR_NOT_INVOKED"; + case GRPC_CALL_ERROR_NOT_ON_CLIENT: + return "GRPC_CALL_ERROR_NOT_ON_CLIENT"; + case GRPC_CALL_ERROR_NOT_ON_SERVER: + return "GRPC_CALL_ERROR_NOT_ON_SERVER"; + case GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE: + return "GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE"; + case GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH: + return "GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH"; + case GRPC_CALL_ERROR_TOO_MANY_OPERATIONS: + return "GRPC_CALL_ERROR_TOO_MANY_OPERATIONS"; + case GRPC_CALL_OK: + return "GRPC_CALL_OK"; + default: + return "GRPC_CALL_ERROR_UNKNOW"; + } +} diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c index 8bd6ae6372..37e7930a55 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.c +++ b/src/python/grpcio/grpc/_cython/imports.generated.c @@ -124,6 +124,7 @@ grpc_tracer_set_enabled_type grpc_tracer_set_enabled_import; grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; +grpc_call_error_to_string_type grpc_call_error_to_string_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -390,6 +391,7 @@ void pygrpc_load_imports(HMODULE library) { grpc_header_key_is_legal_import = (grpc_header_key_is_legal_type) GetProcAddress(library, "grpc_header_key_is_legal"); grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); + grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h index 272e85b485..380b065733 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/python/grpcio/grpc/_cython/imports.generated.h @@ -322,6 +322,9 @@ extern grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_ typedef int(*grpc_is_binary_header_type)(const char *key, size_t length); extern grpc_is_binary_header_type grpc_is_binary_header_import; #define grpc_is_binary_header grpc_is_binary_header_import +typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); +extern grpc_call_error_to_string_type grpc_call_error_to_string_import; +#define grpc_call_error_to_string grpc_call_error_to_string_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 56db4ec686..8633f9347c 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -124,6 +124,7 @@ grpc_tracer_set_enabled_type grpc_tracer_set_enabled_import; grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; +grpc_call_error_to_string_type grpc_call_error_to_string_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -386,6 +387,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_header_key_is_legal_import = (grpc_header_key_is_legal_type) GetProcAddress(library, "grpc_header_key_is_legal"); grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); + grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index c526f434c6..da328367d5 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -322,6 +322,9 @@ extern grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_ typedef int(*grpc_is_binary_header_type)(const char *key, size_t length); extern grpc_is_binary_header_type grpc_is_binary_header_import; #define grpc_is_binary_header grpc_is_binary_header_import +typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); +extern grpc_call_error_to_string_type grpc_call_error_to_string_import; +#define grpc_call_error_to_string grpc_call_error_to_string_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import -- cgit v1.2.3 From 01907123f6323a7494551e7a45e342dcdc068864 Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Thu, 21 Apr 2016 15:09:13 -0700 Subject: generate_projects.sh and fix copyright year --- grpc.def | 1 + include/grpc++/impl/codegen/completion_queue.h | 2 +- include/grpc++/server_builder.h | 2 +- include/grpc/grpc.h | 2 +- src/core/lib/surface/completion_queue.c | 2 +- src/core/lib/surface/completion_queue.h | 2 +- src/core/lib/surface/server.c | 2 +- src/cpp/server/server_builder.cc | 2 +- src/proto/grpc/binary_log/v1alpha/log.proto | 2 +- src/python/grpcio/grpc/_cython/imports.generated.c | 2 ++ src/python/grpcio/grpc/_cython/imports.generated.h | 3 +++ src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 ++ src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 +++ tools/fuzzer/runners/client_fuzzer.sh | 2 +- tools/fuzzer/runners/hpack_parser_fuzzer_test.sh | 2 +- tools/fuzzer/runners/http_fuzzer_test.sh | 2 +- tools/fuzzer/runners/json_fuzzer_test.sh | 2 +- tools/fuzzer/runners/nanopb_fuzzer_response_test.sh | 2 +- tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh | 2 +- tools/fuzzer/runners/server_fuzzer.sh | 2 +- tools/fuzzer/runners/uri_fuzzer_test.sh | 2 +- 21 files changed, 27 insertions(+), 16 deletions(-) (limited to 'src/python/grpcio') diff --git a/grpc.def b/grpc.def index f81aa1b05a..943b464c31 100644 --- a/grpc.def +++ b/grpc.def @@ -77,6 +77,7 @@ EXPORTS grpc_server_request_registered_call grpc_server_create grpc_server_register_completion_queue + grpc_server_register_non_listening_completion_queue grpc_server_add_insecure_http2_port grpc_server_start grpc_server_shutdown_and_notify diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h index d489a90c69..1b84b44705 100644 --- a/include/grpc++/impl/codegen/completion_queue.h +++ b/include/grpc++/impl/codegen/completion_queue.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h index 85af9aa57f..5275bd3ac1 100644 --- a/include/grpc++/server_builder.h +++ b/include/grpc++/server_builder.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 059bd2ebc7..ee15b9d88d 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c index f6f7ac880c..d5eb24270e 100644 --- a/src/core/lib/surface/completion_queue.c +++ b/src/core/lib/surface/completion_queue.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h index ee3e044840..1528ca4ad8 100644 --- a/src/core/lib/surface/completion_queue.h +++ b/src/core/lib/surface/completion_queue.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index c34ec04d2d..0a84d8e7cd 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index c0d13951d7..9cd7cb2da3 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/proto/grpc/binary_log/v1alpha/log.proto b/src/proto/grpc/binary_log/v1alpha/log.proto index 6cc473be74..83166cd410 100644 --- a/src/proto/grpc/binary_log/v1alpha/log.proto +++ b/src/proto/grpc/binary_log/v1alpha/log.proto @@ -105,4 +105,4 @@ message Message { // The contents of the message. May be a prefix instead of the complete // message. bytes data = 5; -} \ No newline at end of file +} diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c index 8bd6ae6372..edad9a3131 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.c +++ b/src/python/grpcio/grpc/_cython/imports.generated.c @@ -115,6 +115,7 @@ grpc_server_register_method_type grpc_server_register_method_import; grpc_server_request_registered_call_type grpc_server_request_registered_call_import; grpc_server_create_type grpc_server_create_import; grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import; +grpc_server_register_non_listening_completion_queue_type grpc_server_register_non_listening_completion_queue_import; grpc_server_add_insecure_http2_port_type grpc_server_add_insecure_http2_port_import; grpc_server_start_type grpc_server_start_import; grpc_server_shutdown_and_notify_type grpc_server_shutdown_and_notify_import; @@ -381,6 +382,7 @@ void pygrpc_load_imports(HMODULE library) { grpc_server_request_registered_call_import = (grpc_server_request_registered_call_type) GetProcAddress(library, "grpc_server_request_registered_call"); grpc_server_create_import = (grpc_server_create_type) GetProcAddress(library, "grpc_server_create"); grpc_server_register_completion_queue_import = (grpc_server_register_completion_queue_type) GetProcAddress(library, "grpc_server_register_completion_queue"); + grpc_server_register_non_listening_completion_queue_import = (grpc_server_register_non_listening_completion_queue_type) GetProcAddress(library, "grpc_server_register_non_listening_completion_queue"); grpc_server_add_insecure_http2_port_import = (grpc_server_add_insecure_http2_port_type) GetProcAddress(library, "grpc_server_add_insecure_http2_port"); grpc_server_start_import = (grpc_server_start_type) GetProcAddress(library, "grpc_server_start"); grpc_server_shutdown_and_notify_import = (grpc_server_shutdown_and_notify_type) GetProcAddress(library, "grpc_server_shutdown_and_notify"); diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h index 272e85b485..7354de4ba2 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/python/grpcio/grpc/_cython/imports.generated.h @@ -295,6 +295,9 @@ extern grpc_server_create_type grpc_server_create_import; typedef void(*grpc_server_register_completion_queue_type)(grpc_server *server, grpc_completion_queue *cq, void *reserved); extern grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import; #define grpc_server_register_completion_queue grpc_server_register_completion_queue_import +typedef void(*grpc_server_register_non_listening_completion_queue_type)(grpc_server *server, grpc_completion_queue *q, void *reserved); +extern grpc_server_register_non_listening_completion_queue_type grpc_server_register_non_listening_completion_queue_import; +#define grpc_server_register_non_listening_completion_queue grpc_server_register_non_listening_completion_queue_import typedef int(*grpc_server_add_insecure_http2_port_type)(grpc_server *server, const char *addr); extern grpc_server_add_insecure_http2_port_type grpc_server_add_insecure_http2_port_import; #define grpc_server_add_insecure_http2_port grpc_server_add_insecure_http2_port_import diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 56db4ec686..149ce6c48a 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -115,6 +115,7 @@ grpc_server_register_method_type grpc_server_register_method_import; grpc_server_request_registered_call_type grpc_server_request_registered_call_import; grpc_server_create_type grpc_server_create_import; grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import; +grpc_server_register_non_listening_completion_queue_type grpc_server_register_non_listening_completion_queue_import; grpc_server_add_insecure_http2_port_type grpc_server_add_insecure_http2_port_import; grpc_server_start_type grpc_server_start_import; grpc_server_shutdown_and_notify_type grpc_server_shutdown_and_notify_import; @@ -377,6 +378,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_server_request_registered_call_import = (grpc_server_request_registered_call_type) GetProcAddress(library, "grpc_server_request_registered_call"); grpc_server_create_import = (grpc_server_create_type) GetProcAddress(library, "grpc_server_create"); grpc_server_register_completion_queue_import = (grpc_server_register_completion_queue_type) GetProcAddress(library, "grpc_server_register_completion_queue"); + grpc_server_register_non_listening_completion_queue_import = (grpc_server_register_non_listening_completion_queue_type) GetProcAddress(library, "grpc_server_register_non_listening_completion_queue"); grpc_server_add_insecure_http2_port_import = (grpc_server_add_insecure_http2_port_type) GetProcAddress(library, "grpc_server_add_insecure_http2_port"); grpc_server_start_import = (grpc_server_start_type) GetProcAddress(library, "grpc_server_start"); grpc_server_shutdown_and_notify_import = (grpc_server_shutdown_and_notify_type) GetProcAddress(library, "grpc_server_shutdown_and_notify"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index c526f434c6..098319db77 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -295,6 +295,9 @@ extern grpc_server_create_type grpc_server_create_import; typedef void(*grpc_server_register_completion_queue_type)(grpc_server *server, grpc_completion_queue *cq, void *reserved); extern grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import; #define grpc_server_register_completion_queue grpc_server_register_completion_queue_import +typedef void(*grpc_server_register_non_listening_completion_queue_type)(grpc_server *server, grpc_completion_queue *q, void *reserved); +extern grpc_server_register_non_listening_completion_queue_type grpc_server_register_non_listening_completion_queue_import; +#define grpc_server_register_non_listening_completion_queue grpc_server_register_non_listening_completion_queue_import typedef int(*grpc_server_add_insecure_http2_port_type)(grpc_server *server, const char *addr); extern grpc_server_add_insecure_http2_port_type grpc_server_add_insecure_http2_port_import; #define grpc_server_add_insecure_http2_port grpc_server_add_insecure_http2_port_import diff --git a/tools/fuzzer/runners/client_fuzzer.sh b/tools/fuzzer/runners/client_fuzzer.sh index 239d552c57..97d4e60d90 100644 --- a/tools/fuzzer/runners/client_fuzzer.sh +++ b/tools/fuzzer/runners/client_fuzzer.sh @@ -33,7 +33,7 @@ flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048" if [ "$jobs" != "1" ] then - flags="-jobs=$jobs -workers=$jobs" + flags="-jobs=$jobs -workers=$jobs $flags" fi if [ "$config" == "asan-trace-cmp" ] diff --git a/tools/fuzzer/runners/hpack_parser_fuzzer_test.sh b/tools/fuzzer/runners/hpack_parser_fuzzer_test.sh index e69b4b4dfe..c6f70a623d 100644 --- a/tools/fuzzer/runners/hpack_parser_fuzzer_test.sh +++ b/tools/fuzzer/runners/hpack_parser_fuzzer_test.sh @@ -33,7 +33,7 @@ flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=512" if [ "$jobs" != "1" ] then - flags="-jobs=$jobs -workers=$jobs" + flags="-jobs=$jobs -workers=$jobs $flags" fi if [ "$config" == "asan-trace-cmp" ] diff --git a/tools/fuzzer/runners/http_fuzzer_test.sh b/tools/fuzzer/runners/http_fuzzer_test.sh index c190ba40b6..bb54a23814 100644 --- a/tools/fuzzer/runners/http_fuzzer_test.sh +++ b/tools/fuzzer/runners/http_fuzzer_test.sh @@ -33,7 +33,7 @@ flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048" if [ "$jobs" != "1" ] then - flags="-jobs=$jobs -workers=$jobs" + flags="-jobs=$jobs -workers=$jobs $flags" fi if [ "$config" == "asan-trace-cmp" ] diff --git a/tools/fuzzer/runners/json_fuzzer_test.sh b/tools/fuzzer/runners/json_fuzzer_test.sh index 9fc6271976..e11e25dc09 100644 --- a/tools/fuzzer/runners/json_fuzzer_test.sh +++ b/tools/fuzzer/runners/json_fuzzer_test.sh @@ -33,7 +33,7 @@ flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=512" if [ "$jobs" != "1" ] then - flags="-jobs=$jobs -workers=$jobs" + flags="-jobs=$jobs -workers=$jobs $flags" fi if [ "$config" == "asan-trace-cmp" ] diff --git a/tools/fuzzer/runners/nanopb_fuzzer_response_test.sh b/tools/fuzzer/runners/nanopb_fuzzer_response_test.sh index bbcebf11cc..97359277ce 100644 --- a/tools/fuzzer/runners/nanopb_fuzzer_response_test.sh +++ b/tools/fuzzer/runners/nanopb_fuzzer_response_test.sh @@ -33,7 +33,7 @@ flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=128" if [ "$jobs" != "1" ] then - flags="-jobs=$jobs -workers=$jobs" + flags="-jobs=$jobs -workers=$jobs $flags" fi if [ "$config" == "asan-trace-cmp" ] diff --git a/tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh b/tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh index e9099bac04..2dfaa2372f 100644 --- a/tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh +++ b/tools/fuzzer/runners/nanopb_fuzzer_serverlist_test.sh @@ -33,7 +33,7 @@ flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=128" if [ "$jobs" != "1" ] then - flags="-jobs=$jobs -workers=$jobs" + flags="-jobs=$jobs -workers=$jobs $flags" fi if [ "$config" == "asan-trace-cmp" ] diff --git a/tools/fuzzer/runners/server_fuzzer.sh b/tools/fuzzer/runners/server_fuzzer.sh index 28ca8b3271..fc0567f670 100644 --- a/tools/fuzzer/runners/server_fuzzer.sh +++ b/tools/fuzzer/runners/server_fuzzer.sh @@ -33,7 +33,7 @@ flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048" if [ "$jobs" != "1" ] then - flags="-jobs=$jobs -workers=$jobs" + flags="-jobs=$jobs -workers=$jobs $flags" fi if [ "$config" == "asan-trace-cmp" ] diff --git a/tools/fuzzer/runners/uri_fuzzer_test.sh b/tools/fuzzer/runners/uri_fuzzer_test.sh index 7dac54ec51..5f33e73465 100644 --- a/tools/fuzzer/runners/uri_fuzzer_test.sh +++ b/tools/fuzzer/runners/uri_fuzzer_test.sh @@ -33,7 +33,7 @@ flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=128" if [ "$jobs" != "1" ] then - flags="-jobs=$jobs -workers=$jobs" + flags="-jobs=$jobs -workers=$jobs $flags" fi if [ "$config" == "asan-trace-cmp" ] -- cgit v1.2.3 From 7f0793ad623ae1dd2b175306a0e7eb060d53511b Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Mon, 25 Apr 2016 12:35:58 -0700 Subject: Updated load balancer proto to v1 --- BUILD | 12 +- Makefile | 18 +- binding.gyp | 2 +- build.yaml | 6 +- config.m4 | 4 +- gRPC.podspec | 6 +- grpc.gemspec | 4 +- package.xml | 4 +- src/core/ext/lb_policy/grpclb/load_balancer_api.c | 14 +- src/core/ext/lb_policy/grpclb/load_balancer_api.h | 10 +- .../grpclb/proto/grpc/lb/v0/load_balancer.pb.c | 119 -------------- .../grpclb/proto/grpc/lb/v0/load_balancer.pb.h | 182 --------------------- .../grpclb/proto/grpc/lb/v1/load_balancer.pb.c | 118 +++++++++++++ .../grpclb/proto/grpc/lb/v1/load_balancer.pb.h | 178 ++++++++++++++++++++ src/proto/grpc/lb/v0/load_balancer.options | 6 - src/proto/grpc/lb/v0/load_balancer.proto | 144 ---------------- src/proto/grpc/lb/v1/load_balancer.options | 6 + src/proto/grpc/lb/v1/load_balancer.proto | 141 ++++++++++++++++ src/python/grpcio/grpc_core_dependencies.py | 2 +- test/cpp/grpclb/grpclb_api_test.cc | 11 +- tools/codegen/core/gen_nano_proto.sh | 6 +- tools/distrib/check_include_guards.py | 2 +- tools/distrib/check_nanopb_output.sh | 6 +- tools/doxygen/Doxyfile.core.internal | 4 +- tools/run_tests/sources_and_headers.json | 10 +- vsprojects/vcxproj/grpc/grpc.vcxproj | 4 +- vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 12 +- .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 4 +- .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 12 +- .../test/grpclb_api_test/grpclb_api_test.vcxproj | 8 +- .../grpclb_api_test.vcxproj.filters | 8 +- 31 files changed, 525 insertions(+), 538 deletions(-) delete mode 100644 src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c delete mode 100644 src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h create mode 100644 src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c create mode 100644 src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h delete mode 100644 src/proto/grpc/lb/v0/load_balancer.options delete mode 100644 src/proto/grpc/lb/v0/load_balancer.proto create mode 100644 src/proto/grpc/lb/v1/load_balancer.options create mode 100644 src/proto/grpc/lb/v1/load_balancer.proto (limited to 'src/python/grpcio') diff --git a/BUILD b/BUILD index f8e7661ad4..ff5220bc8e 100644 --- a/BUILD +++ b/BUILD @@ -284,7 +284,7 @@ cc_library( "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", "src/core/ext/census/aggregation.h", "src/core/ext/census/census_interface.h", "src/core/ext/census/census_rpc_stats.h", @@ -438,7 +438,7 @@ cc_library( "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", "src/core/ext/lb_policy/round_robin/round_robin.c", "src/core/ext/resolver/dns/native/dns_resolver.c", @@ -615,7 +615,7 @@ cc_library( "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", "src/core/ext/census/aggregation.h", "src/core/ext/census/census_interface.h", "src/core/ext/census/census_rpc_stats.h", @@ -751,7 +751,7 @@ cc_library( "src/core/ext/resolver/dns/native/dns_resolver.c", "src/core/ext/resolver/sockaddr/sockaddr_resolver.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", "src/core/ext/lb_policy/round_robin/round_robin.c", "src/core/ext/census/context.c", @@ -1450,7 +1450,7 @@ objc_library( "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", "src/core/ext/lb_policy/round_robin/round_robin.c", "src/core/ext/resolver/dns/native/dns_resolver.c", @@ -1620,7 +1620,7 @@ objc_library( "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", "src/core/ext/census/aggregation.h", "src/core/ext/census/census_interface.h", "src/core/ext/census/census_rpc_stats.h", diff --git a/Makefile b/Makefile index 12022c2dd9..027a24664a 100644 --- a/Makefile +++ b/Makefile @@ -1862,15 +1862,15 @@ $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc: $(Q) echo "$(GRPCXX_UNSECURE_PC_FILE)" | tr , '\n' >$@ ifeq ($(NO_PROTOC),true) -$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc: protoc_dep_error -$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc: protoc_dep_error +$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc: protoc_dep_error +$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: protoc_dep_error else -$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc: src/proto/grpc/lb/v0/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) +$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[PROTOC] Generating protobuf CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) --cpp_out=$(GENDIR) $< -$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v0/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) +$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` $(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $< @@ -2597,7 +2597,7 @@ LIBGRPC_SRC = \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ + src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ @@ -2917,7 +2917,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/resolver/dns/native/dns_resolver.c \ src/core/ext/resolver/sockaddr/sockaddr_resolver.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ + src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ @@ -10602,7 +10602,7 @@ endif GRPCLB_API_TEST_SRC = \ - $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc \ + $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \ test/cpp/grpclb/grpclb_api_test.cc \ GRPCLB_API_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPCLB_API_TEST_SRC)))) @@ -10634,7 +10634,7 @@ endif endif -$(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v0/load_balancer.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a +$(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v1/load_balancer.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a @@ -10645,7 +10645,7 @@ ifneq ($(NO_DEPS),true) -include $(GRPCLB_API_TEST_OBJS:.o=.dep) endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc +$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc HYBRID_END2END_TEST_SRC = \ diff --git a/binding.gyp b/binding.gyp index 058743edbf..0fecc66c46 100644 --- a/binding.gyp +++ b/binding.gyp @@ -708,7 +708,7 @@ 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_decode.c', 'third_party/nanopb/pb_encode.c', diff --git a/build.yaml b/build.yaml index 26308e8db5..d5cfb3c2d6 100644 --- a/build.yaml +++ b/build.yaml @@ -359,10 +359,10 @@ filegroups: - name: grpc_lb_policy_grpclb headers: - src/core/ext/lb_policy/grpclb/load_balancer_api.h - - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h + - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h src: - src/core/ext/lb_policy/grpclb/load_balancer_api.c - - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c + - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c uses: - grpc_base - grpc_client_config @@ -2601,7 +2601,7 @@ targets: build: test language: c++ src: - - src/proto/grpc/lb/v0/load_balancer.proto + - src/proto/grpc/lb/v1/load_balancer.proto - test/cpp/grpclb/grpclb_api_test.cc deps: - grpc++_test_util diff --git a/config.m4 b/config.m4 index 2d930a648e..c60297213d 100644 --- a/config.m4 +++ b/config.m4 @@ -227,7 +227,7 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ - src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ + src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ @@ -553,7 +553,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/client_config) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb) - PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/pick_first) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/round_robin) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/resolver/dns/native) diff --git a/gRPC.podspec b/gRPC.podspec index d66e03354b..6f631c1c55 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -286,7 +286,7 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', 'third_party/nanopb/pb_common.h', 'third_party/nanopb/pb_decode.h', @@ -472,7 +472,7 @@ Pod::Spec.new do |s| 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_decode.c', 'third_party/nanopb/pb_encode.c', @@ -628,7 +628,7 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', 'third_party/nanopb/pb_common.h', 'third_party/nanopb/pb_decode.h', diff --git a/grpc.gemspec b/grpc.gemspec index f83b7d3587..1512da6b56 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -298,7 +298,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_config/subchannel_index.h ) s.files += %w( src/core/ext/client_config/uri_parser.h ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h ) - s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h ) + s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h ) s.files += %w( third_party/nanopb/pb.h ) s.files += %w( third_party/nanopb/pb_common.h ) s.files += %w( third_party/nanopb/pb_decode.h ) @@ -456,7 +456,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c ) - s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c ) + s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c ) s.files += %w( third_party/nanopb/pb_common.c ) s.files += %w( third_party/nanopb/pb_decode.c ) s.files += %w( third_party/nanopb/pb_encode.c ) diff --git a/package.xml b/package.xml index d192ebde2c..295901aaff 100644 --- a/package.xml +++ b/package.xml @@ -301,7 +301,7 @@ - + @@ -459,7 +459,7 @@ - + diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.c b/src/core/ext/lb_policy/grpclb/load_balancer_api.c index 459d6d9954..59b89997dd 100644 --- a/src/core/ext/lb_policy/grpclb/load_balancer_api.c +++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.c @@ -50,7 +50,7 @@ static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field, decode_serverlist_arg *dec_arg = *arg; if (dec_arg->first_pass != 0) { /* first pass */ grpc_grpclb_server server; - if (!pb_decode(stream, grpc_lb_v0_Server_fields, &server)) { + if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) { return false; } dec_arg->num_servers++; @@ -61,7 +61,7 @@ static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field, dec_arg->servers = gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers); } - if (!pb_decode(stream, grpc_lb_v0_Server_fields, server)) { + if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) { return false; } dec_arg->servers[dec_arg->i++] = server; @@ -87,13 +87,13 @@ gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request) { pb_ostream_t outputstream; gpr_slice slice; memset(&sizestream, 0, sizeof(pb_ostream_t)); - pb_encode(&sizestream, grpc_lb_v0_LoadBalanceRequest_fields, request); + pb_encode(&sizestream, grpc_lb_v1_LoadBalanceRequest_fields, request); encoded_length = sizestream.bytes_written; slice = gpr_slice_malloc(encoded_length); outputstream = pb_ostream_from_buffer(GPR_SLICE_START_PTR(slice), encoded_length); - GPR_ASSERT(pb_encode(&outputstream, grpc_lb_v0_LoadBalanceRequest_fields, + GPR_ASSERT(pb_encode(&outputstream, grpc_lb_v1_LoadBalanceRequest_fields, request) != 0); return slice; } @@ -109,7 +109,7 @@ grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response) { GPR_SLICE_LENGTH(encoded_response)); grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response)); memset(res, 0, sizeof(*res)); - status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res); + status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, res); if (!status) { grpc_grpclb_response_destroy(res); return NULL; @@ -132,7 +132,7 @@ grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist( res->server_list.servers.funcs.decode = decode_serverlist; res->server_list.servers.arg = &arg; arg.first_pass = 1; - status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res); + status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, res); if (!status) { grpc_grpclb_response_destroy(res); return NULL; @@ -140,7 +140,7 @@ grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist( arg.first_pass = 0; status = - pb_decode(&stream_at_start, grpc_lb_v0_LoadBalanceResponse_fields, res); + pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, res); if (!status) { grpc_grpclb_response_destroy(res); return NULL; diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/lb_policy/grpclb/load_balancer_api.h index 968f7d278a..71b5616d0c 100644 --- a/src/core/ext/lb_policy/grpclb/load_balancer_api.h +++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.h @@ -37,7 +37,7 @@ #include #include "src/core/ext/client_config/lb_policy_factory.h" -#include "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h" +#include "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" #ifdef __cplusplus extern "C" { @@ -45,10 +45,10 @@ extern "C" { #define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128 -typedef grpc_lb_v0_LoadBalanceRequest grpc_grpclb_request; -typedef grpc_lb_v0_LoadBalanceResponse grpc_grpclb_response; -typedef grpc_lb_v0_Server grpc_grpclb_server; -typedef grpc_lb_v0_Duration grpc_grpclb_duration; +typedef grpc_lb_v1_LoadBalanceRequest grpc_grpclb_request; +typedef grpc_lb_v1_LoadBalanceResponse grpc_grpclb_response; +typedef grpc_lb_v1_Server grpc_grpclb_server; +typedef grpc_lb_v1_Duration grpc_grpclb_duration; typedef struct grpc_grpclb_serverlist { grpc_grpclb_server **servers; size_t num_servers; diff --git a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c deleted file mode 100644 index 9719673181..0000000000 --- a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.3.5-dev */ - -#include "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h" - -#if PB_PROTO_HEADER_VERSION != 30 -#error Regenerate this file with the current version of nanopb generator. -#endif - - - -const pb_field_t grpc_lb_v0_Duration_fields[3] = { - PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v0_Duration, seconds, seconds, 0), - PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v0_Duration, nanos, seconds, 0), - PB_LAST_FIELD -}; - -const pb_field_t grpc_lb_v0_LoadBalanceRequest_fields[3] = { - PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v0_LoadBalanceRequest, initial_request, initial_request, &grpc_lb_v0_InitialLoadBalanceRequest_fields), - PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v0_LoadBalanceRequest, client_stats, initial_request, &grpc_lb_v0_ClientStats_fields), - PB_LAST_FIELD -}; - -const pb_field_t grpc_lb_v0_InitialLoadBalanceRequest_fields[2] = { - PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v0_InitialLoadBalanceRequest, name, name, 0), - PB_LAST_FIELD -}; - -const pb_field_t grpc_lb_v0_ClientStats_fields[4] = { - PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v0_ClientStats, total_requests, total_requests, 0), - PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v0_ClientStats, client_rpc_errors, total_requests, 0), - PB_FIELD( 3, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v0_ClientStats, dropped_requests, client_rpc_errors, 0), - PB_LAST_FIELD -}; - -const pb_field_t grpc_lb_v0_LoadBalanceResponse_fields[3] = { - PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v0_LoadBalanceResponse, initial_response, initial_response, &grpc_lb_v0_InitialLoadBalanceResponse_fields), - PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v0_LoadBalanceResponse, server_list, initial_response, &grpc_lb_v0_ServerList_fields), - PB_LAST_FIELD -}; - -const pb_field_t grpc_lb_v0_InitialLoadBalanceResponse_fields[4] = { - PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v0_InitialLoadBalanceResponse, client_config, client_config, 0), - PB_FIELD( 2, STRING , OPTIONAL, STATIC , OTHER, grpc_lb_v0_InitialLoadBalanceResponse, load_balancer_delegate, client_config, 0), - PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &grpc_lb_v0_Duration_fields), - PB_LAST_FIELD -}; - -const pb_field_t grpc_lb_v0_ServerList_fields[3] = { - PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, grpc_lb_v0_ServerList, servers, servers, &grpc_lb_v0_Server_fields), - PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v0_ServerList, expiration_interval, servers, &grpc_lb_v0_Duration_fields), - PB_LAST_FIELD -}; - -const pb_field_t grpc_lb_v0_Server_fields[5] = { - PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v0_Server, ip_address, ip_address, 0), - PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v0_Server, port, ip_address, 0), - PB_FIELD( 3, BYTES , OPTIONAL, STATIC , OTHER, grpc_lb_v0_Server, load_balance_token, port, 0), - PB_FIELD( 4, BOOL , OPTIONAL, STATIC , OTHER, grpc_lb_v0_Server, drop_request, load_balance_token, 0), - PB_LAST_FIELD -}; - - -/* Check that field information fits in pb_field_t */ -#if !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_32BIT - * compile-time option. You can do that in pb.h or on compiler command line. - * - * The reason you need to do this is that some of your messages contain tag - * numbers or field sizes that are larger than what can fit in 8 or 16 bit - * field descriptors. - */ -PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v0_ServerList, servers) < 65536 && pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server) -#endif - -#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_16BIT - * compile-time option. You can do that in pb.h or on compiler command line. - * - * The reason you need to do this is that some of your messages contain tag - * numbers or field sizes that are larger than what can fit in the default - * 8 bit descriptors. - */ -PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v0_ServerList, servers) < 256 && pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server) -#endif - - diff --git a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h deleted file mode 100644 index 3599f881bb..0000000000 --- a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.3.5-dev */ - -#ifndef PB_LOAD_BALANCER_PB_H_INCLUDED -#define PB_LOAD_BALANCER_PB_H_INCLUDED -#include "third_party/nanopb/pb.h" -#if PB_PROTO_HEADER_VERSION != 30 -#error Regenerate this file with the current version of nanopb generator. -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Struct definitions */ -typedef struct _grpc_lb_v0_ClientStats { - bool has_total_requests; - int64_t total_requests; - bool has_client_rpc_errors; - int64_t client_rpc_errors; - bool has_dropped_requests; - int64_t dropped_requests; -} grpc_lb_v0_ClientStats; - -typedef struct _grpc_lb_v0_Duration { - bool has_seconds; - int64_t seconds; - bool has_nanos; - int32_t nanos; -} grpc_lb_v0_Duration; - -typedef struct _grpc_lb_v0_InitialLoadBalanceRequest { - bool has_name; - char name[128]; -} grpc_lb_v0_InitialLoadBalanceRequest; - -typedef PB_BYTES_ARRAY_T(64) grpc_lb_v0_Server_load_balance_token_t; -typedef struct _grpc_lb_v0_Server { - bool has_ip_address; - char ip_address[46]; - bool has_port; - int32_t port; - bool has_load_balance_token; - grpc_lb_v0_Server_load_balance_token_t load_balance_token; - bool has_drop_request; - bool drop_request; -} grpc_lb_v0_Server; - -typedef struct _grpc_lb_v0_InitialLoadBalanceResponse { - bool has_client_config; - char client_config[64]; - bool has_load_balancer_delegate; - char load_balancer_delegate[64]; - bool has_client_stats_report_interval; - grpc_lb_v0_Duration client_stats_report_interval; -} grpc_lb_v0_InitialLoadBalanceResponse; - -typedef struct _grpc_lb_v0_LoadBalanceRequest { - bool has_initial_request; - grpc_lb_v0_InitialLoadBalanceRequest initial_request; - bool has_client_stats; - grpc_lb_v0_ClientStats client_stats; -} grpc_lb_v0_LoadBalanceRequest; - -typedef struct _grpc_lb_v0_ServerList { - pb_callback_t servers; - bool has_expiration_interval; - grpc_lb_v0_Duration expiration_interval; -} grpc_lb_v0_ServerList; - -typedef struct _grpc_lb_v0_LoadBalanceResponse { - bool has_initial_response; - grpc_lb_v0_InitialLoadBalanceResponse initial_response; - bool has_server_list; - grpc_lb_v0_ServerList server_list; -} grpc_lb_v0_LoadBalanceResponse; - -/* Default values for struct fields */ - -/* Initializer values for message structs */ -#define grpc_lb_v0_Duration_init_default {false, 0, false, 0} -#define grpc_lb_v0_LoadBalanceRequest_init_default {false, grpc_lb_v0_InitialLoadBalanceRequest_init_default, false, grpc_lb_v0_ClientStats_init_default} -#define grpc_lb_v0_InitialLoadBalanceRequest_init_default {false, ""} -#define grpc_lb_v0_ClientStats_init_default {false, 0, false, 0, false, 0} -#define grpc_lb_v0_LoadBalanceResponse_init_default {false, grpc_lb_v0_InitialLoadBalanceResponse_init_default, false, grpc_lb_v0_ServerList_init_default} -#define grpc_lb_v0_InitialLoadBalanceResponse_init_default {false, "", false, "", false, grpc_lb_v0_Duration_init_default} -#define grpc_lb_v0_ServerList_init_default {{{NULL}, NULL}, false, grpc_lb_v0_Duration_init_default} -#define grpc_lb_v0_Server_init_default {false, "", false, 0, false, {0, {0}}, false, 0} -#define grpc_lb_v0_Duration_init_zero {false, 0, false, 0} -#define grpc_lb_v0_LoadBalanceRequest_init_zero {false, grpc_lb_v0_InitialLoadBalanceRequest_init_zero, false, grpc_lb_v0_ClientStats_init_zero} -#define grpc_lb_v0_InitialLoadBalanceRequest_init_zero {false, ""} -#define grpc_lb_v0_ClientStats_init_zero {false, 0, false, 0, false, 0} -#define grpc_lb_v0_LoadBalanceResponse_init_zero {false, grpc_lb_v0_InitialLoadBalanceResponse_init_zero, false, grpc_lb_v0_ServerList_init_zero} -#define grpc_lb_v0_InitialLoadBalanceResponse_init_zero {false, "", false, "", false, grpc_lb_v0_Duration_init_zero} -#define grpc_lb_v0_ServerList_init_zero {{{NULL}, NULL}, false, grpc_lb_v0_Duration_init_zero} -#define grpc_lb_v0_Server_init_zero {false, "", false, 0, false, {0, {0}}, false, 0} - -/* Field tags (for use in manual encoding/decoding) */ -#define grpc_lb_v0_ClientStats_total_requests_tag 1 -#define grpc_lb_v0_ClientStats_client_rpc_errors_tag 2 -#define grpc_lb_v0_ClientStats_dropped_requests_tag 3 -#define grpc_lb_v0_Duration_seconds_tag 1 -#define grpc_lb_v0_Duration_nanos_tag 2 -#define grpc_lb_v0_InitialLoadBalanceRequest_name_tag 1 -#define grpc_lb_v0_Server_ip_address_tag 1 -#define grpc_lb_v0_Server_port_tag 2 -#define grpc_lb_v0_Server_load_balance_token_tag 3 -#define grpc_lb_v0_Server_drop_request_tag 4 -#define grpc_lb_v0_InitialLoadBalanceResponse_client_config_tag 1 -#define grpc_lb_v0_InitialLoadBalanceResponse_load_balancer_delegate_tag 2 -#define grpc_lb_v0_InitialLoadBalanceResponse_client_stats_report_interval_tag 3 -#define grpc_lb_v0_LoadBalanceRequest_initial_request_tag 1 -#define grpc_lb_v0_LoadBalanceRequest_client_stats_tag 2 -#define grpc_lb_v0_ServerList_servers_tag 1 -#define grpc_lb_v0_ServerList_expiration_interval_tag 3 -#define grpc_lb_v0_LoadBalanceResponse_initial_response_tag 1 -#define grpc_lb_v0_LoadBalanceResponse_server_list_tag 2 - -/* Struct field encoding specification for nanopb */ -extern const pb_field_t grpc_lb_v0_Duration_fields[3]; -extern const pb_field_t grpc_lb_v0_LoadBalanceRequest_fields[3]; -extern const pb_field_t grpc_lb_v0_InitialLoadBalanceRequest_fields[2]; -extern const pb_field_t grpc_lb_v0_ClientStats_fields[4]; -extern const pb_field_t grpc_lb_v0_LoadBalanceResponse_fields[3]; -extern const pb_field_t grpc_lb_v0_InitialLoadBalanceResponse_fields[4]; -extern const pb_field_t grpc_lb_v0_ServerList_fields[3]; -extern const pb_field_t grpc_lb_v0_Server_fields[5]; - -/* Maximum encoded size of messages (where known) */ -#define grpc_lb_v0_Duration_size 22 -#define grpc_lb_v0_LoadBalanceRequest_size 169 -#define grpc_lb_v0_InitialLoadBalanceRequest_size 131 -#define grpc_lb_v0_ClientStats_size 33 -#define grpc_lb_v0_LoadBalanceResponse_size (165 + grpc_lb_v0_ServerList_size) -#define grpc_lb_v0_InitialLoadBalanceResponse_size 156 -#define grpc_lb_v0_Server_size 127 - -/* Message IDs (where set with "msgid" option) */ -#ifdef PB_MSGID - -#define LOAD_BALANCER_MESSAGES \ - - -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c new file mode 100644 index 0000000000..52e11c40bb --- /dev/null +++ b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c @@ -0,0 +1,118 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.5-dev */ + +#include "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" + +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t grpc_lb_v1_Duration_fields[3] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v1_Duration, seconds, seconds, 0), + PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Duration, nanos, seconds, 0), + PB_LAST_FIELD +}; + +const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3] = { + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_LoadBalanceRequest, initial_request, initial_request, &grpc_lb_v1_InitialLoadBalanceRequest_fields), + PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_LoadBalanceRequest, client_stats, initial_request, &grpc_lb_v1_ClientStats_fields), + PB_LAST_FIELD +}; + +const pb_field_t grpc_lb_v1_InitialLoadBalanceRequest_fields[2] = { + PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v1_InitialLoadBalanceRequest, name, name, 0), + PB_LAST_FIELD +}; + +const pb_field_t grpc_lb_v1_ClientStats_fields[4] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v1_ClientStats, total_requests, total_requests, 0), + PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, client_rpc_errors, total_requests, 0), + PB_FIELD( 3, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, dropped_requests, client_rpc_errors, 0), + PB_LAST_FIELD +}; + +const pb_field_t grpc_lb_v1_LoadBalanceResponse_fields[3] = { + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_LoadBalanceResponse, initial_response, initial_response, &grpc_lb_v1_InitialLoadBalanceResponse_fields), + PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_LoadBalanceResponse, server_list, initial_response, &grpc_lb_v1_ServerList_fields), + PB_LAST_FIELD +}; + +const pb_field_t grpc_lb_v1_InitialLoadBalanceResponse_fields[3] = { + PB_FIELD( 2, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v1_InitialLoadBalanceResponse, load_balancer_delegate, load_balancer_delegate, 0), + PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &grpc_lb_v1_Duration_fields), + PB_LAST_FIELD +}; + +const pb_field_t grpc_lb_v1_ServerList_fields[3] = { + PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, grpc_lb_v1_ServerList, servers, servers, &grpc_lb_v1_Server_fields), + PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ServerList, expiration_interval, servers, &grpc_lb_v1_Duration_fields), + PB_LAST_FIELD +}; + +const pb_field_t grpc_lb_v1_Server_fields[5] = { + PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v1_Server, ip_address, ip_address, 0), + PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Server, port, ip_address, 0), + PB_FIELD( 3, STRING , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Server, load_balance_token, port, 0), + PB_FIELD( 4, BOOL , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Server, drop_request, load_balance_token, 0), + PB_LAST_FIELD +}; + + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v1_ServerList, servers) < 65536 && pb_membersize(grpc_lb_v1_ServerList, expiration_interval) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256 && pb_membersize(grpc_lb_v1_ServerList, expiration_interval) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) +#endif + + diff --git a/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h new file mode 100644 index 0000000000..d5dc39ab94 --- /dev/null +++ b/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h @@ -0,0 +1,178 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.5-dev */ + +#ifndef PB_LOAD_BALANCER_PB_H_INCLUDED +#define PB_LOAD_BALANCER_PB_H_INCLUDED +#include "third_party/nanopb/pb.h" +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct definitions */ +typedef struct _grpc_lb_v1_ClientStats { + bool has_total_requests; + int64_t total_requests; + bool has_client_rpc_errors; + int64_t client_rpc_errors; + bool has_dropped_requests; + int64_t dropped_requests; +} grpc_lb_v1_ClientStats; + +typedef struct _grpc_lb_v1_Duration { + bool has_seconds; + int64_t seconds; + bool has_nanos; + int32_t nanos; +} grpc_lb_v1_Duration; + +typedef struct _grpc_lb_v1_InitialLoadBalanceRequest { + bool has_name; + char name[128]; +} grpc_lb_v1_InitialLoadBalanceRequest; + +typedef struct _grpc_lb_v1_Server { + bool has_ip_address; + char ip_address[46]; + bool has_port; + int32_t port; + bool has_load_balance_token; + char load_balance_token[64]; + bool has_drop_request; + bool drop_request; +} grpc_lb_v1_Server; + +typedef struct _grpc_lb_v1_InitialLoadBalanceResponse { + bool has_load_balancer_delegate; + char load_balancer_delegate[64]; + bool has_client_stats_report_interval; + grpc_lb_v1_Duration client_stats_report_interval; +} grpc_lb_v1_InitialLoadBalanceResponse; + +typedef struct _grpc_lb_v1_LoadBalanceRequest { + bool has_initial_request; + grpc_lb_v1_InitialLoadBalanceRequest initial_request; + bool has_client_stats; + grpc_lb_v1_ClientStats client_stats; +} grpc_lb_v1_LoadBalanceRequest; + +typedef struct _grpc_lb_v1_ServerList { + pb_callback_t servers; + bool has_expiration_interval; + grpc_lb_v1_Duration expiration_interval; +} grpc_lb_v1_ServerList; + +typedef struct _grpc_lb_v1_LoadBalanceResponse { + bool has_initial_response; + grpc_lb_v1_InitialLoadBalanceResponse initial_response; + bool has_server_list; + grpc_lb_v1_ServerList server_list; +} grpc_lb_v1_LoadBalanceResponse; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define grpc_lb_v1_Duration_init_default {false, 0, false, 0} +#define grpc_lb_v1_LoadBalanceRequest_init_default {false, grpc_lb_v1_InitialLoadBalanceRequest_init_default, false, grpc_lb_v1_ClientStats_init_default} +#define grpc_lb_v1_InitialLoadBalanceRequest_init_default {false, ""} +#define grpc_lb_v1_ClientStats_init_default {false, 0, false, 0, false, 0} +#define grpc_lb_v1_LoadBalanceResponse_init_default {false, grpc_lb_v1_InitialLoadBalanceResponse_init_default, false, grpc_lb_v1_ServerList_init_default} +#define grpc_lb_v1_InitialLoadBalanceResponse_init_default {false, "", false, grpc_lb_v1_Duration_init_default} +#define grpc_lb_v1_ServerList_init_default {{{NULL}, NULL}, false, grpc_lb_v1_Duration_init_default} +#define grpc_lb_v1_Server_init_default {false, "", false, 0, false, "", false, 0} +#define grpc_lb_v1_Duration_init_zero {false, 0, false, 0} +#define grpc_lb_v1_LoadBalanceRequest_init_zero {false, grpc_lb_v1_InitialLoadBalanceRequest_init_zero, false, grpc_lb_v1_ClientStats_init_zero} +#define grpc_lb_v1_InitialLoadBalanceRequest_init_zero {false, ""} +#define grpc_lb_v1_ClientStats_init_zero {false, 0, false, 0, false, 0} +#define grpc_lb_v1_LoadBalanceResponse_init_zero {false, grpc_lb_v1_InitialLoadBalanceResponse_init_zero, false, grpc_lb_v1_ServerList_init_zero} +#define grpc_lb_v1_InitialLoadBalanceResponse_init_zero {false, "", false, grpc_lb_v1_Duration_init_zero} +#define grpc_lb_v1_ServerList_init_zero {{{NULL}, NULL}, false, grpc_lb_v1_Duration_init_zero} +#define grpc_lb_v1_Server_init_zero {false, "", false, 0, false, "", false, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define grpc_lb_v1_ClientStats_total_requests_tag 1 +#define grpc_lb_v1_ClientStats_client_rpc_errors_tag 2 +#define grpc_lb_v1_ClientStats_dropped_requests_tag 3 +#define grpc_lb_v1_Duration_seconds_tag 1 +#define grpc_lb_v1_Duration_nanos_tag 2 +#define grpc_lb_v1_InitialLoadBalanceRequest_name_tag 1 +#define grpc_lb_v1_Server_ip_address_tag 1 +#define grpc_lb_v1_Server_port_tag 2 +#define grpc_lb_v1_Server_load_balance_token_tag 3 +#define grpc_lb_v1_Server_drop_request_tag 4 +#define grpc_lb_v1_InitialLoadBalanceResponse_load_balancer_delegate_tag 2 +#define grpc_lb_v1_InitialLoadBalanceResponse_client_stats_report_interval_tag 3 +#define grpc_lb_v1_LoadBalanceRequest_initial_request_tag 1 +#define grpc_lb_v1_LoadBalanceRequest_client_stats_tag 2 +#define grpc_lb_v1_ServerList_servers_tag 1 +#define grpc_lb_v1_ServerList_expiration_interval_tag 3 +#define grpc_lb_v1_LoadBalanceResponse_initial_response_tag 1 +#define grpc_lb_v1_LoadBalanceResponse_server_list_tag 2 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t grpc_lb_v1_Duration_fields[3]; +extern const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3]; +extern const pb_field_t grpc_lb_v1_InitialLoadBalanceRequest_fields[2]; +extern const pb_field_t grpc_lb_v1_ClientStats_fields[4]; +extern const pb_field_t grpc_lb_v1_LoadBalanceResponse_fields[3]; +extern const pb_field_t grpc_lb_v1_InitialLoadBalanceResponse_fields[3]; +extern const pb_field_t grpc_lb_v1_ServerList_fields[3]; +extern const pb_field_t grpc_lb_v1_Server_fields[5]; + +/* Maximum encoded size of messages (where known) */ +#define grpc_lb_v1_Duration_size 22 +#define grpc_lb_v1_LoadBalanceRequest_size 169 +#define grpc_lb_v1_InitialLoadBalanceRequest_size 131 +#define grpc_lb_v1_ClientStats_size 33 +#define grpc_lb_v1_LoadBalanceResponse_size (98 + grpc_lb_v1_ServerList_size) +#define grpc_lb_v1_InitialLoadBalanceResponse_size 90 +#define grpc_lb_v1_Server_size 127 + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define LOAD_BALANCER_MESSAGES \ + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/proto/grpc/lb/v0/load_balancer.options b/src/proto/grpc/lb/v0/load_balancer.options deleted file mode 100644 index 6d4528f838..0000000000 --- a/src/proto/grpc/lb/v0/load_balancer.options +++ /dev/null @@ -1,6 +0,0 @@ -grpc.lb.v0.InitialLoadBalanceRequest.name max_size:128 -grpc.lb.v0.InitialLoadBalanceResponse.client_config max_size:64 -grpc.lb.v0.InitialLoadBalanceResponse.load_balancer_delegate max_size:64 -grpc.lb.v0.Server.ip_address max_size:46 -grpc.lb.v0.Server.load_balance_token max_size:64 -load_balancer.proto no_unions:true diff --git a/src/proto/grpc/lb/v0/load_balancer.proto b/src/proto/grpc/lb/v0/load_balancer.proto deleted file mode 100644 index e88a4f8c4a..0000000000 --- a/src/proto/grpc/lb/v0/load_balancer.proto +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2016, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package grpc.lb.v0; - -message Duration { - - // Signed seconds of the span of time. Must be from -315,576,000,000 - // to +315,576,000,000 inclusive. - int64 seconds = 1; - - // Signed fractions of a second at nanosecond resolution of the span - // of time. Durations less than one second are represented with a 0 - // `seconds` field and a positive or negative `nanos` field. For durations - // of one second or more, a non-zero value for the `nanos` field must be - // of the same sign as the `seconds` field. Must be from -999,999,999 - // to +999,999,999 inclusive. - int32 nanos = 2; -} - -service LoadBalancer { - // Bidirectional rpc to get a list of servers. - rpc BalanceLoad(stream LoadBalanceRequest) - returns (stream LoadBalanceResponse); -} - -message LoadBalanceRequest { - oneof load_balance_request_type { - // This message should be sent on the first request to the load balancer. - InitialLoadBalanceRequest initial_request = 1; - - // The client stats should be periodically reported to the load balancer - // based on the duration defined in the InitialLoadBalanceResponse. - ClientStats client_stats = 2; - } -} - -message InitialLoadBalanceRequest { - // Name of load balanced service (IE, service.grpc.gslb.google.com) - string name = 1; -} - -// Contains client level statistics that are useful to load balancing. Each -// count should be reset to zero after reporting the stats. -message ClientStats { - // The total number of requests sent by the client since the last report. - int64 total_requests = 1; - - // The number of client rpc errors since the last report. - int64 client_rpc_errors = 2; - - // The number of dropped requests since the last report. - int64 dropped_requests = 3; -} - -message LoadBalanceResponse { - oneof load_balance_response_type { - // This message should be sent on the first response to the client. - InitialLoadBalanceResponse initial_response = 1; - - // Contains the list of servers selected by the load balancer. The client - // should send requests to these servers in the specified order. - ServerList server_list = 2; - } -} - -message InitialLoadBalanceResponse { - oneof initial_response_type { - // Contains gRPC config options like RPC deadline or flow control. - // TODO(yetianx): Change to ClientConfig after it is defined. - string client_config = 1; - - // This is an application layer redirect that indicates the client should - // use the specified server for load balancing. When this field is set in - // the response, the client should open a separate connection to the - // load_balancer_delegate and call the BalanceLoad method. - string load_balancer_delegate = 2; - } - - // This interval defines how often the client should send the client stats - // to the load balancer. Stats should only be reported when the duration is - // positive. - Duration client_stats_report_interval = 3; -} - -message ServerList { - // Contains a list of servers selected by the load balancer. The list will - // be updated when server resolutions change or as needed to balance load - // across more servers. The client should consume the server list in order - // unless instructed otherwise via the client_config. - repeated Server servers = 1; - - // Indicates the amount of time that the client should consider this server - // list as valid. It may be considered stale after waiting this interval of - // time after receiving the list. If the interval is not positive, the - // client can assume the list is valid until the next list is received. - Duration expiration_interval = 3; -} - -message Server { - // A resolved address and port for the server. The IP address string may - // either be an IPv4 or IPv6 address. - string ip_address = 1; - int32 port = 2; - - // An opaque token that is passed from the client to the server in metadata. - // The server may expect this token to indicate that the request from the - // client was load balanced. - // TODO(yetianx): Not used right now, and will be used after implementing - // load report. - bytes load_balance_token = 3; - - // Indicates whether this particular request should be dropped by the client - // when this server is chosen from the list. - bool drop_request = 4; -} diff --git a/src/proto/grpc/lb/v1/load_balancer.options b/src/proto/grpc/lb/v1/load_balancer.options new file mode 100644 index 0000000000..d90366996e --- /dev/null +++ b/src/proto/grpc/lb/v1/load_balancer.options @@ -0,0 +1,6 @@ +grpc.lb.v1.InitialLoadBalanceRequest.name max_size:128 +grpc.lb.v1.InitialLoadBalanceResponse.client_config max_size:64 +grpc.lb.v1.InitialLoadBalanceResponse.load_balancer_delegate max_size:64 +grpc.lb.v1.Server.ip_address max_size:46 +grpc.lb.v1.Server.load_balance_token max_size:64 +load_balancer.proto no_unions:true diff --git a/src/proto/grpc/lb/v1/load_balancer.proto b/src/proto/grpc/lb/v1/load_balancer.proto new file mode 100644 index 0000000000..1bcad0b1d4 --- /dev/null +++ b/src/proto/grpc/lb/v1/load_balancer.proto @@ -0,0 +1,141 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package grpc.lb.v1; + +message Duration { + + // Signed seconds of the span of time. Must be from -315,576,000,000 + // to +315,576,000,000 inclusive. + int64 seconds = 1; + + // Signed fractions of a second at nanosecond resolution of the span + // of time. Durations less than one second are represented with a 0 + // `seconds` field and a positive or negative `nanos` field. For durations + // of one second or more, a non-zero value for the `nanos` field must be + // of the same sign as the `seconds` field. Must be from -999,999,999 + // to +999,999,999 inclusive. + int32 nanos = 2; +} + +service LoadBalancer { + // Bidirectional rpc to get a list of servers. + rpc BalanceLoad(stream LoadBalanceRequest) + returns (stream LoadBalanceResponse); +} + +message LoadBalanceRequest { + oneof load_balance_request_type { + // This message should be sent on the first request to the load balancer. + InitialLoadBalanceRequest initial_request = 1; + + // The client stats should be periodically reported to the load balancer + // based on the duration defined in the InitialLoadBalanceResponse. + ClientStats client_stats = 2; + } +} + +message InitialLoadBalanceRequest { + // Name of load balanced service (IE, service.grpc.gslb.google.com) + string name = 1; +} + +// Contains client level statistics that are useful to load balancing. Each +// count should be reset to zero after reporting the stats. +message ClientStats { + // The total number of requests sent by the client since the last report. + int64 total_requests = 1; + + // The number of client rpc errors since the last report. + int64 client_rpc_errors = 2; + + // The number of dropped requests since the last report. + int64 dropped_requests = 3; +} + +message LoadBalanceResponse { + oneof load_balance_response_type { + // This message should be sent on the first response to the client. + InitialLoadBalanceResponse initial_response = 1; + + // Contains the list of servers selected by the load balancer. The client + // should send requests to these servers in the specified order. + ServerList server_list = 2; + } +} + +message InitialLoadBalanceResponse { + oneof initial_response_type { + // TODO(zhangkun83): ClientConfig not yet defined + //ClientConfig client_config = 1; + + // This is an application layer redirect that indicates the client should + // use the specified server for load balancing. When this field is set in + // the response, the client should open a separate connection to the + // load_balancer_delegate and call the BalanceLoad method. + string load_balancer_delegate = 2; + } + + // This interval defines how often the client should send the client stats + // to the load balancer. Stats should only be reported when the duration is + // positive. + Duration client_stats_report_interval = 3; +} + +message ServerList { + // Contains a list of servers selected by the load balancer. The list will + // be updated when server resolutions change or as needed to balance load + // across more servers. The client should consume the server list in order + // unless instructed otherwise via the client_config. + repeated Server servers = 1; + + // Indicates the amount of time that the client should consider this server + // list as valid. It may be considered stale after waiting this interval of + // time after receiving the list. If the interval is not positive, the + // client can assume the list is valid until the next list is received. + Duration expiration_interval = 3; +} + +message Server { + // A resolved address and port for the server. The IP address string may + // either be an IPv4 or IPv6 address. + string ip_address = 1; + int32 port = 2; + + // An opaque token that is passed from the client to the server in metadata. + // The server may expect this token to indicate that the request from the + // client was load balanced. + string load_balance_token = 3; + + // Indicates whether this particular request should be dropped by the client + // when this server is chosen from the list. + bool drop_request = 4; +} diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index c5a0a398b4..e1fe5fc1f6 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -221,7 +221,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', 'third_party/nanopb/pb_decode.c', 'third_party/nanopb/pb_encode.c', diff --git a/test/cpp/grpclb/grpclb_api_test.cc b/test/cpp/grpclb/grpclb_api_test.cc index 92f93c869c..bf77878e0a 100644 --- a/test/cpp/grpclb/grpclb_api_test.cc +++ b/test/cpp/grpclb/grpclb_api_test.cc @@ -35,13 +35,13 @@ #include #include "src/core/ext/lb_policy/grpclb/load_balancer_api.h" -#include "src/proto/grpc/lb/v0/load_balancer.pb.h" // C++ version +#include "src/proto/grpc/lb/v1/load_balancer.pb.h" // C++ version namespace grpc { namespace { -using grpc::lb::v0::LoadBalanceRequest; -using grpc::lb::v0::LoadBalanceResponse; +using grpc::lb::v1::LoadBalanceRequest; +using grpc::lb::v1::LoadBalanceResponse; class GrpclbTest : public ::testing::Test {}; @@ -60,9 +60,7 @@ TEST_F(GrpclbTest, CreateRequest) { TEST_F(GrpclbTest, ParseResponse) { LoadBalanceResponse response; - const std::string client_config_str = "I'm a client config"; auto* initial_response = response.mutable_initial_response(); - initial_response->set_client_config(client_config_str); auto* client_stats_report_interval = initial_response->mutable_client_stats_report_interval(); client_stats_report_interval->set_seconds(123); @@ -73,10 +71,7 @@ TEST_F(GrpclbTest, ParseResponse) { gpr_slice_from_copied_string(encoded_response.c_str()); grpc_grpclb_response* c_response = grpc_grpclb_response_parse(encoded_slice); EXPECT_TRUE(c_response->has_initial_response); - EXPECT_TRUE(c_response->initial_response.has_client_config); EXPECT_FALSE(c_response->initial_response.has_load_balancer_delegate); - EXPECT_TRUE(strcmp(c_response->initial_response.client_config, - client_config_str.c_str()) == 0); EXPECT_EQ(c_response->initial_response.client_stats_report_interval.seconds, 123); EXPECT_EQ(c_response->initial_response.client_stats_report_interval.nanos, diff --git a/tools/codegen/core/gen_nano_proto.sh b/tools/codegen/core/gen_nano_proto.sh index e2d2f672e9..b216a20379 100755 --- a/tools/codegen/core/gen_nano_proto.sh +++ b/tools/codegen/core/gen_nano_proto.sh @@ -29,11 +29,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# # Example usage: # tools/codegen/core/gen_nano_proto.sh \ -# src/proto/grpc/lb/v0/load_balancer.proto -# $PWD/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0 +# src/proto/grpc/lb/v1/load_balancer.proto \ +# $PWD/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1 \ +# src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1 # # Exit statuses: # 1: Incorrect number of arguments diff --git a/tools/distrib/check_include_guards.py b/tools/distrib/check_include_guards.py index 897a899e7e..b1fdb942cd 100755 --- a/tools/distrib/check_include_guards.py +++ b/tools/distrib/check_include_guards.py @@ -169,7 +169,7 @@ argp.add_argument('--precommit', args = argp.parse_args() KNOWN_BAD = set([ - 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', + 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', ]) diff --git a/tools/distrib/check_nanopb_output.sh b/tools/distrib/check_nanopb_output.sh index 92cb8ecbb4..c0707051a6 100755 --- a/tools/distrib/check_nanopb_output.sh +++ b/tools/distrib/check_nanopb_output.sh @@ -58,15 +58,15 @@ popd # # Checks for load_balancer.proto # -readonly LOAD_BALANCER_GRPC_OUTPUT_PATH='src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0' +readonly LOAD_BALANCER_GRPC_OUTPUT_PATH='src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1' # nanopb-compile the proto to a temp location ./tools/codegen/core/gen_nano_proto.sh \ - src/proto/grpc/lb/v0/load_balancer.proto \ + src/proto/grpc/lb/v1/load_balancer.proto \ "$NANOPB_TMP_OUTPUT" \ "$LOAD_BALANCER_GRPC_OUTPUT_PATH" # compare outputs to checked compiled code -if ! diff -r $NANOPB_TMP_OUTPUT src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0; then +if ! diff -r $NANOPB_TMP_OUTPUT src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1; then echo "Outputs differ: $NANOPB_TMP_OUTPUT vs $LOAD_BALANCER_GRPC_OUTPUT_PATH" exit 2 fi diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 3a774a70d6..ebf573d3b2 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -913,7 +913,7 @@ src/core/ext/client_config/subchannel_call_holder.h \ src/core/ext/client_config/subchannel_index.h \ src/core/ext/client_config/uri_parser.h \ src/core/ext/lb_policy/grpclb/load_balancer_api.h \ -src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h \ +src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h \ third_party/nanopb/pb.h \ third_party/nanopb/pb_common.h \ third_party/nanopb/pb_decode.h \ @@ -1071,7 +1071,7 @@ src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ -src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ +src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 38e68f3b1a..2599df2303 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -2201,8 +2201,8 @@ "grpc_test_util" ], "headers": [ - "src/proto/grpc/lb/v0/load_balancer.grpc.pb.h", - "src/proto/grpc/lb/v0/load_balancer.pb.h" + "src/proto/grpc/lb/v1/load_balancer.grpc.pb.h", + "src/proto/grpc/lb/v1/load_balancer.pb.h" ], "language": "c++", "name": "grpclb_api_test", @@ -5860,15 +5860,15 @@ ], "headers": [ "src/core/ext/lb_policy/grpclb/load_balancer_api.h", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h" + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" ], "language": "c", "name": "grpc_lb_policy_grpclb", "src": [ "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", - "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h" + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", + "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" ], "third_party": false, "type": "filegroup" diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 4eec05a3b1..26109c7102 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -422,7 +422,7 @@ - + @@ -729,7 +729,7 @@ - + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 17c88c4805..8d7072b04a 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -442,8 +442,8 @@ src\core\ext\lb_policy\grpclb - - src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0 + + src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1 third_party\nanopb @@ -959,8 +959,8 @@ src\core\ext\lb_policy\grpclb - - src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0 + + src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1 third_party\nanopb @@ -1037,8 +1037,8 @@ {adf7e553-94ef-14fd-e845-03104f00a06f} - - {0406d191-8817-38c3-a562-e3541201f424} + + {bc357e2d-8ddd-a688-88a3-255228fc0818} {b63ded00-b24f-708e-333f-ce199e421875} diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 26050dcf74..31ab8f4ba4 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -397,7 +397,7 @@ - + @@ -668,7 +668,7 @@ - + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index a4acf513bc..869d92c738 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -388,8 +388,8 @@ src\core\ext\lb_policy\grpclb - - src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0 + + src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1 third_party\nanopb @@ -851,8 +851,8 @@ src\core\ext\lb_policy\grpclb - - src\core\ext\lb_policy\grpclb\proto\grpc\lb\v0 + + src\core\ext\lb_policy\grpclb\proto\grpc\lb\v1 third_party\nanopb @@ -929,8 +929,8 @@ {21858d9d-30b5-8847-5882-6b47df0fa293} - - {1795a20b-3e7c-e27d-eae1-96582fa9a958} + + {e9256e96-ea3d-c1fd-6426-9d53d9f08f66} {e27f9ecf-97bb-1a2e-3135-a41f732dcf55} diff --git a/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj index 1509ece9f9..91b11a1f0f 100644 --- a/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj +++ b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj @@ -160,13 +160,13 @@ - + - + - + - + diff --git a/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters index 6c57b8c162..50f0a3eac2 100644 --- a/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters +++ b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters @@ -1,8 +1,8 @@ - - src\proto\grpc\lb\v0 + + src\proto\grpc\lb\v1 test\cpp\grpclb @@ -22,8 +22,8 @@ {2981699e-c196-c599-bc17-c177770f89ee} - - {3d04774a-1c2f-e100-435e-08af5d539250} + + {6cce8ddf-d9a9-1d71-0810-d1e6f8685d76} {64736e1d-eb77-664f-34ab-6cf41263d3d8} -- cgit v1.2.3 From d06e9291cb10c5757e1b7852248af341c2cd3390 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Wed, 27 Apr 2016 14:59:17 -0700 Subject: Add Windows-specifics to Python docs --- examples/python/README.md | 11 +++++++++-- src/python/grpcio/README.rst | 13 +++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src/python/grpcio') diff --git a/examples/python/README.md b/examples/python/README.md index b57da8f642..9992baa842 100644 --- a/examples/python/README.md +++ b/examples/python/README.md @@ -8,12 +8,19 @@ For this sample, we've already generated the server and client stubs from Install gRPC: - ```sh +```sh $ pip install grpcio ``` Or, to install it system wide: ```sh - $ sudo pip install grpcio + $ sudo pip install grpcio +``` + +If you're on Windows, make sure you installed the `pip.exe` component when you +installed Python. Invoke as above but with `pip.exe` instead of `pip` (you may +also need to invoke from a `cmd.exe` ran as administrator): +```sh + $ pip.exe install grpcio ``` Download the example diff --git a/src/python/grpcio/README.rst b/src/python/grpcio/README.rst index 33a462b66f..cb3f6b87fe 100644 --- a/src/python/grpcio/README.rst +++ b/src/python/grpcio/README.rst @@ -23,6 +23,16 @@ Else system wide (on Ubuntu)... $ sudo pip install grpcio +If you're on Windows make sure that you installed the :code:`pip.exe` component +when you installed Python (if not go back and install it!) then invoke: + +:: + + $ pip.exe install grpcio + +Windows users may need to invoke :code:`pip.exe` from a command line ran as +administrator. + n.b. On Windows and on Mac OS X one *must* have a recent release of :code:`pip` to retrieve the proper wheel from PyPI. Be sure to upgrade to the latest version! @@ -43,6 +53,9 @@ package named :code:`python-dev`). $ pip install -rrequirements.txt $ GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install . +You cannot currently install Python from source on Windows. Things might work +out for you in MSYS2 (follow the Linux instructions), but it isn't officially +supported at the moment. Troubleshooting ~~~~~~~~~~~~~~~ -- cgit v1.2.3 From 832ae81b21025c415fc183b1aa18e063c44180a3 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Wed, 27 Apr 2016 18:38:54 -0700 Subject: Allow additive changes to protos w/o forcing user implementation --- src/compiler/python_generator.cc | 10 +++--- .../tests/protoc_plugin/beta_python_plugin_test.py | 41 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) (limited to 'src/python/grpcio') diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index 02c032800b..59137e1c92 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -190,7 +190,7 @@ bool PrintBetaServicer(const ServiceDescriptor* service, "Documentation", doc, }); out->Print("\n"); - out->Print(dict, "class Beta$Service$Servicer(six.with_metaclass(abc.ABCMeta, object)):\n"); + out->Print(dict, "class Beta$Service$Servicer(object):\n"); { IndentScope raii_class_indent(out); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); @@ -198,12 +198,11 @@ bool PrintBetaServicer(const ServiceDescriptor* service, auto meth = service->method(i); grpc::string arg_name = meth->client_streaming() ? "request_iterator" : "request"; - out->Print("@abc.abstractmethod\n"); out->Print("def $Method$(self, $ArgName$, context):\n", "Method", meth->name(), "ArgName", arg_name); { IndentScope raii_method_indent(out); - out->Print("raise NotImplementedError()\n"); + out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n"); } } } @@ -218,7 +217,7 @@ bool PrintBetaStub(const ServiceDescriptor* service, "Documentation", doc, }); out->Print("\n"); - out->Print(dict, "class Beta$Service$Stub(six.with_metaclass(abc.ABCMeta, object)):\n"); + out->Print(dict, "class Beta$Service$Stub(object):\n"); { IndentScope raii_class_indent(out); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); @@ -227,7 +226,6 @@ bool PrintBetaStub(const ServiceDescriptor* service, grpc::string arg_name = meth->client_streaming() ? "request_iterator" : "request"; auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name}); - out->Print("@abc.abstractmethod\n"); out->Print(methdict, "def $Method$(self, $ArgName$, timeout):\n"); { IndentScope raii_method_indent(out); @@ -450,6 +448,8 @@ bool PrintPreamble(const FileDescriptor* file, out->Print("import six\n"); out->Print("from $Package$ import implementations as beta_implementations\n", "Package", config.beta_package_root); + out->Print("from $Package$ import interfaces as beta_interfaces\n", + "Package", config.beta_package_root); out->Print("from grpc.framework.common import cardinality\n"); out->Print("from grpc.framework.interfaces.face import utilities as face_utilities\n"); return true; diff --git a/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py b/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py index 6fba3d4271..3dc3042e38 100644 --- a/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py +++ b/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py @@ -45,6 +45,7 @@ import unittest from six import moves from grpc.beta import implementations +from grpc.beta import interfaces from grpc.framework.foundation import future from grpc.framework.interfaces.face import face from tests.unit.framework.common import test_constants @@ -178,6 +179,36 @@ def _CreateService(test_pb2): server.stop(0) +@contextlib.contextmanager +def _CreateIncompleteService(test_pb2): + """Provides a servicer backend that fails to implement methods and its stub. + + The servicer is just the implementation of the actual servicer passed to the + face player of the python RPC implementation; the two are detached. + + Args: + test_pb2: The test_pb2 module generated by this test. + + Yields: + A (servicer_methods, stub) pair where servicer_methods is the back-end of + the service bound to the stub and and stub is the stub on which to invoke + RPCs. + """ + servicer_methods = _ServicerMethods(test_pb2) + + class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)): + pass + + servicer = Servicer() + server = getattr(test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) + port = server.add_insecure_port('[::]:0') + server.start() + channel = implementations.insecure_channel('localhost', port) + stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)(channel) + yield servicer_methods, stub + server.stop(0) + + def _streaming_input_request_iterator(test_pb2): for _ in range(3): request = test_pb2.StreamingInputCallRequest() @@ -264,6 +295,16 @@ class PythonPluginTest(unittest.TestCase): with _CreateService(test_pb2) as (servicer, stub): request = test_pb2.SimpleRequest(response_size=13) + def testIncompleteServicer(self): + import protoc_plugin_test_pb2 as test_pb2 + moves.reload_module(test_pb2) + with _CreateIncompleteService(test_pb2) as (servicer, stub): + request = test_pb2.SimpleRequest(response_size=13) + try: + response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT) + except face.AbortionError as error: + self.assertEqual(interfaces.StatusCode.UNIMPLEMENTED, error.code) + def testUnaryCall(self): import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top moves.reload_module(test_pb2) -- cgit v1.2.3 From cab9470ee82ae411558f279c64d296e364237ab8 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Thu, 28 Apr 2016 01:59:36 +0000 Subject: Remove Python alpha/early_adopter implementation This code has been unsupported for more than six months. --- src/python/grpcio/grpc/_adapter/fore.py | 363 ------------ src/python/grpcio/grpc/_adapter/rear.py | 395 ------------- src/python/grpcio/grpc/early_adopter/__init__.py | 35 -- .../grpcio/grpc/early_adopter/implementations.py | 262 --------- src/python/grpcio/grpc/framework/alpha/__init__.py | 35 -- .../grpcio/grpc/framework/alpha/_face_utilities.py | 183 ------ .../grpcio/grpc/framework/alpha/_reexport.py | 205 ------- .../grpcio/grpc/framework/alpha/exceptions.py | 47 -- .../grpcio/grpc/framework/alpha/interfaces.py | 384 ------------- .../grpcio/grpc/framework/alpha/utilities.py | 269 --------- src/python/grpcio/grpc/framework/base/__init__.py | 35 -- .../grpcio/grpc/framework/base/_cancellation.py | 64 --- .../grpcio/grpc/framework/base/_constants.py | 32 -- src/python/grpcio/grpc/framework/base/_context.py | 99 ---- src/python/grpcio/grpc/framework/base/_emission.py | 125 ---- src/python/grpcio/grpc/framework/base/_ends.py | 399 ------------- .../grpcio/grpc/framework/base/_expiration.py | 158 ----- .../grpcio/grpc/framework/base/_ingestion.py | 443 -------------- .../grpcio/grpc/framework/base/_interfaces.py | 266 --------- .../grpcio/grpc/framework/base/_reception.py | 400 ------------- .../grpcio/grpc/framework/base/_termination.py | 204 ------- .../grpcio/grpc/framework/base/_transmission.py | 429 -------------- .../grpcio/grpc/framework/base/exceptions.py | 34 -- .../grpcio/grpc/framework/base/implementations.py | 77 --- src/python/grpcio/grpc/framework/base/in_memory.py | 108 ---- .../grpcio/grpc/framework/base/interfaces.py | 353 ------------ src/python/grpcio/grpc/framework/base/null.py | 56 -- src/python/grpcio/grpc/framework/base/util.py | 94 --- src/python/grpcio/grpc/framework/face/__init__.py | 35 -- src/python/grpcio/grpc/framework/face/_calls.py | 422 -------------- src/python/grpcio/grpc/framework/face/_control.py | 201 ------- src/python/grpcio/grpc/framework/face/_service.py | 187 ------ .../grpcio/grpc/framework/face/demonstration.py | 118 ---- .../grpcio/grpc/framework/face/exceptions.py | 78 --- .../grpcio/grpc/framework/face/implementations.py | 320 ----------- .../grpcio/grpc/framework/face/interfaces.py | 634 --------------------- src/python/grpcio/grpc/framework/face/utilities.py | 177 ------ .../grpcio/tests/unit/framework/face/__init__.py | 30 - .../tests/unit/framework/face/testing/__init__.py | 30 - .../tests/unit/framework/face/testing/base_util.py | 102 ---- ...blocking_invocation_inline_service_test_case.py | 224 -------- .../tests/unit/framework/face/testing/callback.py | 94 --- .../tests/unit/framework/face/testing/control.py | 87 --- .../tests/unit/framework/face/testing/coverage.py | 121 ---- .../tests/unit/framework/face/testing/digest.py | 452 --------------- ...vocation_synchronous_event_service_test_case.py | 378 ------------ ...ocation_asynchronous_event_service_test_case.py | 384 ------------- .../unit/framework/face/testing/interfaces.py | 118 ---- .../tests/unit/framework/face/testing/service.py | 321 ----------- .../unit/framework/face/testing/stock_service.py | 374 ------------ .../tests/unit/framework/face/testing/test_case.py | 81 --- 51 files changed, 10522 deletions(-) delete mode 100644 src/python/grpcio/grpc/_adapter/fore.py delete mode 100644 src/python/grpcio/grpc/_adapter/rear.py delete mode 100644 src/python/grpcio/grpc/early_adopter/__init__.py delete mode 100644 src/python/grpcio/grpc/early_adopter/implementations.py delete mode 100644 src/python/grpcio/grpc/framework/alpha/__init__.py delete mode 100644 src/python/grpcio/grpc/framework/alpha/_face_utilities.py delete mode 100644 src/python/grpcio/grpc/framework/alpha/_reexport.py delete mode 100644 src/python/grpcio/grpc/framework/alpha/exceptions.py delete mode 100644 src/python/grpcio/grpc/framework/alpha/interfaces.py delete mode 100644 src/python/grpcio/grpc/framework/alpha/utilities.py delete mode 100644 src/python/grpcio/grpc/framework/base/__init__.py delete mode 100644 src/python/grpcio/grpc/framework/base/_cancellation.py delete mode 100644 src/python/grpcio/grpc/framework/base/_constants.py delete mode 100644 src/python/grpcio/grpc/framework/base/_context.py delete mode 100644 src/python/grpcio/grpc/framework/base/_emission.py delete mode 100644 src/python/grpcio/grpc/framework/base/_ends.py delete mode 100644 src/python/grpcio/grpc/framework/base/_expiration.py delete mode 100644 src/python/grpcio/grpc/framework/base/_ingestion.py delete mode 100644 src/python/grpcio/grpc/framework/base/_interfaces.py delete mode 100644 src/python/grpcio/grpc/framework/base/_reception.py delete mode 100644 src/python/grpcio/grpc/framework/base/_termination.py delete mode 100644 src/python/grpcio/grpc/framework/base/_transmission.py delete mode 100644 src/python/grpcio/grpc/framework/base/exceptions.py delete mode 100644 src/python/grpcio/grpc/framework/base/implementations.py delete mode 100644 src/python/grpcio/grpc/framework/base/in_memory.py delete mode 100644 src/python/grpcio/grpc/framework/base/interfaces.py delete mode 100644 src/python/grpcio/grpc/framework/base/null.py delete mode 100644 src/python/grpcio/grpc/framework/base/util.py delete mode 100644 src/python/grpcio/grpc/framework/face/__init__.py delete mode 100644 src/python/grpcio/grpc/framework/face/_calls.py delete mode 100644 src/python/grpcio/grpc/framework/face/_control.py delete mode 100644 src/python/grpcio/grpc/framework/face/_service.py delete mode 100644 src/python/grpcio/grpc/framework/face/demonstration.py delete mode 100644 src/python/grpcio/grpc/framework/face/exceptions.py delete mode 100644 src/python/grpcio/grpc/framework/face/implementations.py delete mode 100644 src/python/grpcio/grpc/framework/face/interfaces.py delete mode 100644 src/python/grpcio/grpc/framework/face/utilities.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/__init__.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/__init__.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/base_util.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/callback.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/control.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/coverage.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/digest.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/interfaces.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/service.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/stock_service.py delete mode 100644 src/python/grpcio/tests/unit/framework/face/testing/test_case.py (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/grpc/_adapter/fore.py b/src/python/grpcio/grpc/_adapter/fore.py deleted file mode 100644 index acdd69c420..0000000000 --- a/src/python/grpcio/grpc/_adapter/fore.py +++ /dev/null @@ -1,363 +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. - -"""The RPC-service-side bridge between RPC Framework and GRPC-on-the-wire.""" - -import enum -import logging -import threading -import time - -from grpc._adapter import _common -from grpc._adapter import _intermediary_low as _low -from grpc.framework.base import interfaces as base_interfaces -from grpc.framework.base import null -from grpc.framework.foundation import activated -from grpc.framework.foundation import logging_pool - -_THREAD_POOL_SIZE = 10 - - -@enum.unique -class _LowWrite(enum.Enum): - """The possible categories of low-level write state.""" - - OPEN = 'OPEN' - ACTIVE = 'ACTIVE' - CLOSED = 'CLOSED' - - -def _write(call, rpc_state, payload): - serialized_payload = rpc_state.serializer(payload) - if rpc_state.write.low is _LowWrite.OPEN: - call.write(serialized_payload, call, 0) - rpc_state.write.low = _LowWrite.ACTIVE - else: - rpc_state.write.pending.append(serialized_payload) - - -def _status(call, rpc_state): - call.status(_low.Status(_low.Code.OK, ''), call) - rpc_state.write.low = _LowWrite.CLOSED - - -class ForeLink(base_interfaces.ForeLink, activated.Activated): - """A service-side bridge between RPC Framework and the C-ish _low code.""" - - def __init__( - self, pool, request_deserializers, response_serializers, - root_certificates, key_chain_pairs, port=None): - """Constructor. - - Args: - pool: A thread pool. - request_deserializers: A dict from RPC method names to request object - deserializer behaviors. - response_serializers: A dict from RPC method names to response object - serializer behaviors. - root_certificates: The PEM-encoded client root certificates as a - bytestring or None. - key_chain_pairs: A sequence of PEM-encoded private key-certificate chain - pairs. - port: The port on which to serve, or None to have a port selected - automatically. - """ - self._condition = threading.Condition() - self._pool = pool - self._request_deserializers = request_deserializers - self._response_serializers = response_serializers - self._root_certificates = root_certificates - self._key_chain_pairs = key_chain_pairs - self._requested_port = port - - self._rear_link = null.NULL_REAR_LINK - self._completion_queue = None - self._server = None - self._rpc_states = {} - self._spinning = False - self._port = None - - def _on_stop_event(self): - self._spinning = False - self._condition.notify_all() - - def _on_service_acceptance_event(self, event, server): - """Handle a service invocation event.""" - service_acceptance = event.service_acceptance - if service_acceptance is None: - return - - call = service_acceptance.call - call.accept(self._completion_queue, call) - # TODO(nathaniel): Metadata support. - call.premetadata() - call.read(call) - method = service_acceptance.method - - self._rpc_states[call] = _common.CommonRPCState( - _common.WriteState(_LowWrite.OPEN, _common.HighWrite.OPEN, []), 1, - self._request_deserializers[method], - self._response_serializers[method]) - - ticket = base_interfaces.FrontToBackTicket( - call, 0, base_interfaces.FrontToBackTicket.Kind.COMMENCEMENT, method, - base_interfaces.ServicedSubscription.Kind.FULL, None, None, - service_acceptance.deadline - time.time()) - self._rear_link.accept_front_to_back_ticket(ticket) - - server.service(None) - - def _on_read_event(self, event): - """Handle data arriving during an RPC.""" - call = event.tag - rpc_state = self._rpc_states.get(call, None) - if rpc_state is None: - return - - sequence_number = rpc_state.sequence_number - rpc_state.sequence_number += 1 - if event.bytes is None: - ticket = base_interfaces.FrontToBackTicket( - call, sequence_number, - base_interfaces.FrontToBackTicket.Kind.COMPLETION, None, None, None, - None, None) - else: - call.read(call) - ticket = base_interfaces.FrontToBackTicket( - call, sequence_number, - base_interfaces.FrontToBackTicket.Kind.CONTINUATION, None, None, - None, rpc_state.deserializer(event.bytes), None) - - self._rear_link.accept_front_to_back_ticket(ticket) - - def _on_write_event(self, event): - call = event.tag - rpc_state = self._rpc_states.get(call, None) - if rpc_state is None: - return - - if rpc_state.write.pending: - serialized_payload = rpc_state.write.pending.pop(0) - call.write(serialized_payload, call, 0) - elif rpc_state.write.high is _common.HighWrite.CLOSED: - _status(call, rpc_state) - else: - rpc_state.write.low = _LowWrite.OPEN - - def _on_complete_event(self, event): - if not event.complete_accepted: - logging.error('Complete not accepted! %s', (event,)) - call = event.tag - rpc_state = self._rpc_states.pop(call, None) - if rpc_state is None: - return - - sequence_number = rpc_state.sequence_number - rpc_state.sequence_number += 1 - ticket = base_interfaces.FrontToBackTicket( - call, sequence_number, - base_interfaces.FrontToBackTicket.Kind.TRANSMISSION_FAILURE, None, - None, None, None, None) - self._rear_link.accept_front_to_back_ticket(ticket) - - def _on_finish_event(self, event): - """Handle termination of an RPC.""" - call = event.tag - rpc_state = self._rpc_states.pop(call, None) - if rpc_state is None: - return - - code = event.status.code - if code is _low.Code.OK: - return - - sequence_number = rpc_state.sequence_number - rpc_state.sequence_number += 1 - if code is _low.Code.CANCELLED: - ticket = base_interfaces.FrontToBackTicket( - call, sequence_number, - base_interfaces.FrontToBackTicket.Kind.CANCELLATION, None, None, - None, None, None) - elif code is _low.Code.DEADLINE_EXCEEDED: - ticket = base_interfaces.FrontToBackTicket( - call, sequence_number, - base_interfaces.FrontToBackTicket.Kind.EXPIRATION, None, None, None, - None, None) - else: - # TODO(nathaniel): Better mapping of codes to ticket-categories - ticket = base_interfaces.FrontToBackTicket( - call, sequence_number, - base_interfaces.FrontToBackTicket.Kind.TRANSMISSION_FAILURE, None, - None, None, None, None) - self._rear_link.accept_front_to_back_ticket(ticket) - - def _spin(self, completion_queue, server): - while True: - event = completion_queue.get(None) - - with self._condition: - if event.kind is _low.Event.Kind.STOP: - self._on_stop_event() - return - elif self._server is None: - continue - elif event.kind is _low.Event.Kind.SERVICE_ACCEPTED: - self._on_service_acceptance_event(event, server) - elif event.kind is _low.Event.Kind.READ_ACCEPTED: - self._on_read_event(event) - elif event.kind is _low.Event.Kind.WRITE_ACCEPTED: - self._on_write_event(event) - elif event.kind is _low.Event.Kind.COMPLETE_ACCEPTED: - self._on_complete_event(event) - elif event.kind is _low.Event.Kind.FINISH: - self._on_finish_event(event) - else: - logging.error('Illegal event! %s', (event,)) - - def _continue(self, call, payload): - rpc_state = self._rpc_states.get(call, None) - if rpc_state is None: - return - - _write(call, rpc_state, payload) - - def _complete(self, call, payload): - """Handle completion of the writes of an RPC.""" - rpc_state = self._rpc_states.get(call, None) - if rpc_state is None: - return - - if rpc_state.write.low is _LowWrite.OPEN: - if payload is None: - _status(call, rpc_state) - else: - _write(call, rpc_state, payload) - elif rpc_state.write.low is _LowWrite.ACTIVE: - if payload is not None: - rpc_state.write.pending.append(rpc_state.serializer(payload)) - else: - raise ValueError('Called to complete after having already completed!') - rpc_state.write.high = _common.HighWrite.CLOSED - - def _cancel(self, call): - call.cancel() - self._rpc_states.pop(call, None) - - def join_rear_link(self, rear_link): - """See base_interfaces.ForeLink.join_rear_link for specification.""" - self._rear_link = null.NULL_REAR_LINK if rear_link is None else rear_link - - def _start(self): - """Starts this ForeLink. - - This method must be called before attempting to exchange tickets with this - object. - """ - with self._condition: - address = '[::]:%d' % ( - 0 if self._requested_port is None else self._requested_port) - self._completion_queue = _low.CompletionQueue() - if self._root_certificates is None and not self._key_chain_pairs: - self._server = _low.Server(self._completion_queue) - self._port = self._server.add_http2_addr(address) - else: - server_credentials = _low.ServerCredentials( - self._root_certificates, self._key_chain_pairs, False) - self._server = _low.Server(self._completion_queue) - self._port = self._server.add_secure_http2_addr( - address, server_credentials) - self._server.start() - - self._server.service(None) - - self._pool.submit(self._spin, self._completion_queue, self._server) - self._spinning = True - - return self - - # TODO(nathaniel): Expose graceful-shutdown semantics in which this object - # enters a state in which it finishes ongoing RPCs but refuses new ones. - def _stop(self): - """Stops this ForeLink. - - This method must be called for proper termination of this object, and no - attempts to exchange tickets with this object may be made after this method - has been called. - """ - with self._condition: - self._server.stop() - # TODO(nathaniel): Yep, this is weird. Deleting a server shouldn't have a - # behaviorally significant side-effect. - self._server = None - self._completion_queue.stop() - - while self._spinning: - self._condition.wait() - - self._port = None - - def __enter__(self): - """See activated.Activated.__enter__ for specification.""" - return self._start() - - def __exit__(self, exc_type, exc_val, exc_tb): - """See activated.Activated.__exit__ for specification.""" - self._stop() - return False - - def start(self): - """See activated.Activated.start for specification.""" - return self._start() - - def stop(self): - """See activated.Activated.stop for specification.""" - self._stop() - - def port(self): - """Identifies the port on which this ForeLink is servicing RPCs. - - Returns: - The number of the port on which this ForeLink is servicing RPCs, or None - if this ForeLink is not currently activated and servicing RPCs. - """ - with self._condition: - return self._port - - def accept_back_to_front_ticket(self, ticket): - """See base_interfaces.ForeLink.accept_back_to_front_ticket for spec.""" - with self._condition: - if self._server is None: - return - - if ticket.kind is base_interfaces.BackToFrontTicket.Kind.CONTINUATION: - self._continue(ticket.operation_id, ticket.payload) - elif ticket.kind is base_interfaces.BackToFrontTicket.Kind.COMPLETION: - self._complete(ticket.operation_id, ticket.payload) - else: - self._cancel(ticket.operation_id) diff --git a/src/python/grpcio/grpc/_adapter/rear.py b/src/python/grpcio/grpc/_adapter/rear.py deleted file mode 100644 index 17fa47f746..0000000000 --- a/src/python/grpcio/grpc/_adapter/rear.py +++ /dev/null @@ -1,395 +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. - -"""The RPC-invocation-side bridge between RPC Framework and GRPC-on-the-wire.""" - -import enum -import logging -import threading -import time - -from grpc._adapter import _common -from grpc._adapter import _intermediary_low as _low -from grpc.framework.base import interfaces as base_interfaces -from grpc.framework.base import null -from grpc.framework.foundation import activated -from grpc.framework.foundation import logging_pool - -_THREAD_POOL_SIZE = 10 - -_INVOCATION_EVENT_KINDS = ( - _low.Event.Kind.METADATA_ACCEPTED, - _low.Event.Kind.FINISH -) - - -@enum.unique -class _LowWrite(enum.Enum): - """The possible categories of low-level write state.""" - - OPEN = 'OPEN' - ACTIVE = 'ACTIVE' - CLOSED = 'CLOSED' - - -class _RPCState(object): - """The full state of any tracked RPC. - - Attributes: - call: The _low.Call object for the RPC. - outstanding: The set of Event.Kind values describing expected future events - for the RPC. - active: A boolean indicating whether or not the RPC is active. - common: An _common.RPCState describing additional state for the RPC. - """ - - def __init__(self, call, outstanding, active, common): - self.call = call - self.outstanding = outstanding - self.active = active - self.common = common - - -def _write(operation_id, call, outstanding, write_state, serialized_payload): - if write_state.low is _LowWrite.OPEN: - call.write(serialized_payload, operation_id, 0) - outstanding.add(_low.Event.Kind.WRITE_ACCEPTED) - write_state.low = _LowWrite.ACTIVE - elif write_state.low is _LowWrite.ACTIVE: - write_state.pending.append(serialized_payload) - else: - raise ValueError('Write attempted after writes completed!') - - -class RearLink(base_interfaces.RearLink, activated.Activated): - """An invocation-side bridge between RPC Framework and the C-ish _low code.""" - - def __init__( - self, host, port, pool, request_serializers, response_deserializers, - secure, root_certificates, private_key, certificate_chain, - metadata_transformer=None, server_host_override=None): - """Constructor. - - Args: - host: The host to which to connect for RPC service. - port: The port to which to connect for RPC service. - pool: A thread pool. - request_serializers: A dict from RPC method names to request object - serializer behaviors. - response_deserializers: A dict from RPC method names to response object - deserializer behaviors. - secure: A boolean indicating whether or not to use a secure connection. - root_certificates: The PEM-encoded root certificates or None to ask for - them to be retrieved from a default location. - private_key: The PEM-encoded private key to use or None if no private - key should be used. - certificate_chain: The PEM-encoded certificate chain to use or None if - no certificate chain should be used. - metadata_transformer: A function that given a metadata object produces - another metadata to be used in the underlying communication on the - wire. - server_host_override: (For testing only) the target name used for SSL - host name checking. - """ - self._condition = threading.Condition() - self._host = host - self._port = port - self._pool = pool - self._request_serializers = request_serializers - self._response_deserializers = response_deserializers - - self._fore_link = null.NULL_FORE_LINK - self._completion_queue = None - self._channel = None - self._rpc_states = {} - self._spinning = False - if secure: - self._client_credentials = _low.ClientCredentials( - root_certificates, private_key, certificate_chain) - else: - self._client_credentials = None - self._root_certificates = root_certificates - self._private_key = private_key - self._certificate_chain = certificate_chain - self._metadata_transformer = metadata_transformer - self._server_host_override = server_host_override - - def _on_write_event(self, operation_id, event, rpc_state): - if event.write_accepted: - if rpc_state.common.write.pending: - rpc_state.call.write( - rpc_state.common.write.pending.pop(0), operation_id, 0) - rpc_state.outstanding.add(_low.Event.Kind.WRITE_ACCEPTED) - elif rpc_state.common.write.high is _common.HighWrite.CLOSED: - rpc_state.call.complete(operation_id) - rpc_state.outstanding.add(_low.Event.Kind.COMPLETE_ACCEPTED) - rpc_state.common.write.low = _LowWrite.CLOSED - else: - rpc_state.common.write.low = _LowWrite.OPEN - else: - logging.error('RPC write not accepted! Event: %s', (event,)) - rpc_state.active = False - ticket = base_interfaces.BackToFrontTicket( - operation_id, rpc_state.common.sequence_number, - base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE, None) - rpc_state.common.sequence_number += 1 - self._fore_link.accept_back_to_front_ticket(ticket) - - def _on_read_event(self, operation_id, event, rpc_state): - if event.bytes is not None: - rpc_state.call.read(operation_id) - rpc_state.outstanding.add(_low.Event.Kind.READ_ACCEPTED) - - ticket = base_interfaces.BackToFrontTicket( - operation_id, rpc_state.common.sequence_number, - base_interfaces.BackToFrontTicket.Kind.CONTINUATION, - rpc_state.common.deserializer(event.bytes)) - rpc_state.common.sequence_number += 1 - self._fore_link.accept_back_to_front_ticket(ticket) - - def _on_complete_event(self, operation_id, event, rpc_state): - if not event.complete_accepted: - logging.error('RPC complete not accepted! Event: %s', (event,)) - rpc_state.active = False - ticket = base_interfaces.BackToFrontTicket( - operation_id, rpc_state.common.sequence_number, - base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE, None) - rpc_state.common.sequence_number += 1 - self._fore_link.accept_back_to_front_ticket(ticket) - - # TODO(nathaniel): Metadata support. - def _on_metadata_event(self, operation_id, event, rpc_state): # pylint: disable=unused-argument - rpc_state.call.read(operation_id) - rpc_state.outstanding.add(_low.Event.Kind.READ_ACCEPTED) - - def _on_finish_event(self, operation_id, event, rpc_state): - """Handle termination of an RPC.""" - # TODO(nathaniel): Cover all statuses. - if event.status.code is _low.Code.OK: - kind = base_interfaces.BackToFrontTicket.Kind.COMPLETION - elif event.status.code is _low.Code.CANCELLED: - kind = base_interfaces.BackToFrontTicket.Kind.CANCELLATION - elif event.status.code is _low.Code.DEADLINE_EXCEEDED: - kind = base_interfaces.BackToFrontTicket.Kind.EXPIRATION - else: - kind = base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE - ticket = base_interfaces.BackToFrontTicket( - operation_id, rpc_state.common.sequence_number, kind, None) - rpc_state.common.sequence_number += 1 - self._fore_link.accept_back_to_front_ticket(ticket) - - def _spin(self, completion_queue): - while True: - event = completion_queue.get(None) - operation_id = event.tag - - with self._condition: - rpc_state = self._rpc_states[operation_id] - rpc_state.outstanding.remove(event.kind) - if rpc_state.active and self._completion_queue is not None: - if event.kind is _low.Event.Kind.WRITE_ACCEPTED: - self._on_write_event(operation_id, event, rpc_state) - elif event.kind is _low.Event.Kind.METADATA_ACCEPTED: - self._on_metadata_event(operation_id, event, rpc_state) - elif event.kind is _low.Event.Kind.READ_ACCEPTED: - self._on_read_event(operation_id, event, rpc_state) - elif event.kind is _low.Event.Kind.COMPLETE_ACCEPTED: - self._on_complete_event(operation_id, event, rpc_state) - elif event.kind is _low.Event.Kind.FINISH: - self._on_finish_event(operation_id, event, rpc_state) - else: - logging.error('Illegal RPC event! %s', (event,)) - - if not rpc_state.outstanding: - self._rpc_states.pop(operation_id) - if not self._rpc_states: - self._spinning = False - self._condition.notify_all() - return - - def _invoke(self, operation_id, name, high_state, payload, timeout): - """Invoke an RPC. - - Args: - operation_id: Any object to be used as an operation ID for the RPC. - name: The RPC method name. - high_state: A _common.HighWrite value representing the "high write state" - of the RPC. - payload: A payload object for the RPC or None if no payload was given at - invocation-time. - timeout: A duration of time in seconds to allow for the RPC. - """ - request_serializer = self._request_serializers[name] - call = _low.Call(self._channel, self._completion_queue, name, self._host, time.time() + timeout) - if self._metadata_transformer is not None: - metadata = self._metadata_transformer([]) - for metadata_key, metadata_value in metadata: - call.add_metadata(metadata_key, metadata_value) - call.invoke(self._completion_queue, operation_id, operation_id) - outstanding = set(_INVOCATION_EVENT_KINDS) - - if payload is None: - if high_state is _common.HighWrite.CLOSED: - call.complete(operation_id) - low_state = _LowWrite.CLOSED - outstanding.add(_low.Event.Kind.COMPLETE_ACCEPTED) - else: - low_state = _LowWrite.OPEN - else: - serialized_payload = request_serializer(payload) - call.write(serialized_payload, operation_id, 0) - outstanding.add(_low.Event.Kind.WRITE_ACCEPTED) - low_state = _LowWrite.ACTIVE - - write_state = _common.WriteState(low_state, high_state, []) - common_state = _common.CommonRPCState( - write_state, 0, self._response_deserializers[name], request_serializer) - self._rpc_states[operation_id] = _RPCState( - call, outstanding, True, common_state) - - if not self._spinning: - self._pool.submit(self._spin, self._completion_queue) - self._spinning = True - - def _commence(self, operation_id, name, payload, timeout): - self._invoke(operation_id, name, _common.HighWrite.OPEN, payload, timeout) - - def _continue(self, operation_id, payload): - rpc_state = self._rpc_states.get(operation_id, None) - if rpc_state is None or not rpc_state.active: - return - - _write( - operation_id, rpc_state.call, rpc_state.outstanding, - rpc_state.common.write, rpc_state.common.serializer(payload)) - - def _complete(self, operation_id, payload): - """Close writes associated with an ongoing RPC. - - Args: - operation_id: Any object being use as an operation ID for the RPC. - payload: A payload object for the RPC (and thus the last payload object - for the RPC) or None if no payload was given along with the instruction - to indicate the end of writes for the RPC. - """ - rpc_state = self._rpc_states.get(operation_id, None) - if rpc_state is None or not rpc_state.active: - return - - write_state = rpc_state.common.write - if payload is None: - if write_state.low is _LowWrite.OPEN: - rpc_state.call.complete(operation_id) - rpc_state.outstanding.add(_low.Event.Kind.COMPLETE_ACCEPTED) - write_state.low = _LowWrite.CLOSED - else: - _write( - operation_id, rpc_state.call, rpc_state.outstanding, write_state, - rpc_state.common.serializer(payload)) - write_state.high = _common.HighWrite.CLOSED - - def _entire(self, operation_id, name, payload, timeout): - self._invoke(operation_id, name, _common.HighWrite.CLOSED, payload, timeout) - - def _cancel(self, operation_id): - rpc_state = self._rpc_states.get(operation_id, None) - if rpc_state is not None and rpc_state.active: - rpc_state.call.cancel() - rpc_state.active = False - - def join_fore_link(self, fore_link): - """See base_interfaces.RearLink.join_fore_link for specification.""" - with self._condition: - self._fore_link = null.NULL_FORE_LINK if fore_link is None else fore_link - - def _start(self): - """Starts this RearLink. - - This method must be called before attempting to exchange tickets with this - object. - """ - with self._condition: - self._completion_queue = _low.CompletionQueue() - self._channel = _low.Channel( - '%s:%d' % (self._host, self._port), self._client_credentials, - server_host_override=self._server_host_override) - return self - - def _stop(self): - """Stops this RearLink. - - This method must be called for proper termination of this object, and no - attempts to exchange tickets with this object may be made after this method - has been called. - """ - with self._condition: - self._completion_queue.stop() - self._completion_queue = None - - while self._spinning: - self._condition.wait() - - def __enter__(self): - """See activated.Activated.__enter__ for specification.""" - return self._start() - - def __exit__(self, exc_type, exc_val, exc_tb): - """See activated.Activated.__exit__ for specification.""" - self._stop() - return False - - def start(self): - """See activated.Activated.start for specification.""" - return self._start() - - def stop(self): - """See activated.Activated.stop for specification.""" - self._stop() - - def accept_front_to_back_ticket(self, ticket): - """See base_interfaces.RearLink.accept_front_to_back_ticket for spec.""" - with self._condition: - if self._completion_queue is None: - return - - if ticket.kind is base_interfaces.FrontToBackTicket.Kind.COMMENCEMENT: - self._commence( - ticket.operation_id, ticket.name, ticket.payload, ticket.timeout) - elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.CONTINUATION: - self._continue(ticket.operation_id, ticket.payload) - elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.COMPLETION: - self._complete(ticket.operation_id, ticket.payload) - elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.ENTIRE: - self._entire( - ticket.operation_id, ticket.name, ticket.payload, ticket.timeout) - elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.CANCELLATION: - self._cancel(ticket.operation_id) - else: - # NOTE(nathaniel): All other categories are treated as cancellation. - self._cancel(ticket.operation_id) diff --git a/src/python/grpcio/grpc/early_adopter/__init__.py b/src/python/grpcio/grpc/early_adopter/__init__.py deleted file mode 100644 index bff74be2c7..0000000000 --- a/src/python/grpcio/grpc/early_adopter/__init__.py +++ /dev/null @@ -1,35 +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. - -import warnings - -warnings.simplefilter('always', DeprecationWarning) -warnings.warn('the alpha API (includes this package) is deprecated, ' - 'unmaintained, and no longer tested. Please migrate to the beta ' - 'API.', DeprecationWarning, stacklevel=2) diff --git a/src/python/grpcio/grpc/early_adopter/implementations.py b/src/python/grpcio/grpc/early_adopter/implementations.py deleted file mode 100644 index 9c396aa7ad..0000000000 --- a/src/python/grpcio/grpc/early_adopter/implementations.py +++ /dev/null @@ -1,262 +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. - -"""Entry points into GRPC.""" - -import threading - -from grpc._adapter import fore as _fore -from grpc._adapter import rear as _rear -from grpc.framework.alpha import _face_utilities -from grpc.framework.alpha import _reexport -from grpc.framework.alpha import interfaces -from grpc.framework.base import implementations as _base_implementations -from grpc.framework.base import util as _base_utilities -from grpc.framework.face import implementations as _face_implementations -from grpc.framework.foundation import logging_pool - -_DEFAULT_THREAD_POOL_SIZE = 8 -_ONE_DAY_IN_SECONDS = 24 * 60 * 60 - - -class _Server(interfaces.Server): - - def __init__( - self, breakdown, port, private_key, certificate_chain, - thread_pool_size=_DEFAULT_THREAD_POOL_SIZE): - self._lock = threading.Lock() - self._breakdown = breakdown - self._port = port - if private_key is None or certificate_chain is None: - self._key_chain_pairs = () - else: - self._key_chain_pairs = ((private_key, certificate_chain),) - - self._pool_size = thread_pool_size - self._pool = None - self._back = None - self._fore_link = None - - def _start(self): - with self._lock: - if self._pool is None: - self._pool = logging_pool.pool(self._pool_size) - servicer = _face_implementations.servicer( - self._pool, self._breakdown.implementations, None) - self._back = _base_implementations.back_link( - servicer, self._pool, self._pool, self._pool, _ONE_DAY_IN_SECONDS, - _ONE_DAY_IN_SECONDS) - self._fore_link = _fore.ForeLink( - self._pool, self._breakdown.request_deserializers, - self._breakdown.response_serializers, None, self._key_chain_pairs, - port=self._port) - self._back.join_fore_link(self._fore_link) - self._fore_link.join_rear_link(self._back) - self._fore_link.start() - else: - raise ValueError('Server currently running!') - - def _stop(self): - with self._lock: - if self._pool is None: - raise ValueError('Server not running!') - else: - self._fore_link.stop() - _base_utilities.wait_for_idle(self._back) - self._pool.shutdown(wait=True) - self._fore_link = None - self._back = None - self._pool = None - - def __enter__(self): - self._start() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self._stop() - return False - - def start(self): - self._start() - - def stop(self): - self._stop() - - def port(self): - with self._lock: - return self._fore_link.port() - - -class _Stub(interfaces.Stub): - - def __init__( - self, breakdown, host, port, secure, root_certificates, private_key, - certificate_chain, metadata_transformer=None, server_host_override=None, - thread_pool_size=_DEFAULT_THREAD_POOL_SIZE): - self._lock = threading.Lock() - self._breakdown = breakdown - self._host = host - self._port = port - self._secure = secure - self._root_certificates = root_certificates - self._private_key = private_key - self._certificate_chain = certificate_chain - self._metadata_transformer = metadata_transformer - self._server_host_override = server_host_override - - self._pool_size = thread_pool_size - self._pool = None - self._front = None - self._rear_link = None - self._understub = None - - def __enter__(self): - with self._lock: - if self._pool is None: - self._pool = logging_pool.pool(self._pool_size) - self._front = _base_implementations.front_link( - self._pool, self._pool, self._pool) - self._rear_link = _rear.RearLink( - self._host, self._port, self._pool, - self._breakdown.request_serializers, - self._breakdown.response_deserializers, self._secure, - self._root_certificates, self._private_key, self._certificate_chain, - metadata_transformer=self._metadata_transformer, - server_host_override=self._server_host_override) - self._front.join_rear_link(self._rear_link) - self._rear_link.join_fore_link(self._front) - self._rear_link.start() - self._understub = _face_implementations.dynamic_stub( - self._breakdown.face_cardinalities, self._front, self._pool, '') - else: - raise ValueError('Tried to __enter__ already-__enter__ed Stub!') - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - with self._lock: - if self._pool is None: - raise ValueError('Tried to __exit__ non-__enter__ed Stub!') - else: - self._rear_link.stop() - _base_utilities.wait_for_idle(self._front) - self._pool.shutdown(wait=True) - self._rear_link = None - self._front = None - self._pool = None - self._understub = None - return False - - def __getattr__(self, attr): - with self._lock: - if self._pool is None: - raise ValueError('Tried to __getattr__ non-__enter__ed Stub!') - else: - method_cardinality = self._breakdown.cardinalities.get(attr) - underlying_attr = getattr( - self._understub, self._breakdown.qualified_names.get(attr), None) - if method_cardinality is interfaces.Cardinality.UNARY_UNARY: - return _reexport.unary_unary_sync_async(underlying_attr) - elif method_cardinality is interfaces.Cardinality.UNARY_STREAM: - return lambda request, timeout: _reexport.cancellable_iterator( - underlying_attr(request, timeout)) - elif method_cardinality is interfaces.Cardinality.STREAM_UNARY: - return _reexport.stream_unary_sync_async(underlying_attr) - elif method_cardinality is interfaces.Cardinality.STREAM_STREAM: - return lambda request_iterator, timeout: ( - _reexport.cancellable_iterator(underlying_attr( - request_iterator, timeout))) - else: - raise AttributeError(attr) - - -def stub( - service_name, methods, host, port, metadata_transformer=None, secure=False, - root_certificates=None, private_key=None, certificate_chain=None, - server_host_override=None, thread_pool_size=_DEFAULT_THREAD_POOL_SIZE): - """Constructs an interfaces.Stub. - - Args: - service_name: The package-qualified full name of the service. - methods: A dictionary from RPC method name to - interfaces.RpcMethodInvocationDescription describing the RPCs to be - supported by the created stub. The RPC method names in the dictionary are - not qualified by the service name or decorated in any other way. - host: The host to which to connect for RPC service. - port: The port to which to connect for RPC service. - metadata_transformer: A callable that given a metadata object produces - another metadata object to be used in the underlying communication on the - wire. - secure: Whether or not to construct the stub with a secure connection. - root_certificates: The PEM-encoded root certificates or None to ask for - them to be retrieved from a default location. - private_key: The PEM-encoded private key to use or None if no private key - should be used. - certificate_chain: The PEM-encoded certificate chain to use or None if no - certificate chain should be used. - server_host_override: (For testing only) the target name used for SSL - host name checking. - thread_pool_size: The maximum number of threads to allow in the backing - thread pool. - - Returns: - An interfaces.Stub affording RPC invocation. - """ - breakdown = _face_utilities.break_down_invocation(service_name, methods) - return _Stub( - breakdown, host, port, secure, root_certificates, private_key, - certificate_chain, server_host_override=server_host_override, - metadata_transformer=metadata_transformer, - thread_pool_size=thread_pool_size) - - -def server( - service_name, methods, port, private_key=None, certificate_chain=None, - thread_pool_size=_DEFAULT_THREAD_POOL_SIZE): - """Constructs an interfaces.Server. - - Args: - service_name: The package-qualified full name of the service. - methods: A dictionary from RPC method name to - interfaces.RpcMethodServiceDescription describing the RPCs to - be serviced by the created server. The RPC method names in the dictionary - are not qualified by the service name or decorated in any other way. - port: The port on which to serve or zero to ask for a port to be - automatically selected. - private_key: A pem-encoded private key, or None for an insecure server. - certificate_chain: A pem-encoded certificate chain, or None for an insecure - server. - thread_pool_size: The maximum number of threads to allow in the backing - thread pool. - - Returns: - An interfaces.Server that will serve secure traffic. - """ - breakdown = _face_utilities.break_down_service(service_name, methods) - return _Server(breakdown, port, private_key, certificate_chain, - thread_pool_size=thread_pool_size) diff --git a/src/python/grpcio/grpc/framework/alpha/__init__.py b/src/python/grpcio/grpc/framework/alpha/__init__.py deleted file mode 100644 index bff74be2c7..0000000000 --- a/src/python/grpcio/grpc/framework/alpha/__init__.py +++ /dev/null @@ -1,35 +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. - -import warnings - -warnings.simplefilter('always', DeprecationWarning) -warnings.warn('the alpha API (includes this package) is deprecated, ' - 'unmaintained, and no longer tested. Please migrate to the beta ' - 'API.', DeprecationWarning, stacklevel=2) diff --git a/src/python/grpcio/grpc/framework/alpha/_face_utilities.py b/src/python/grpcio/grpc/framework/alpha/_face_utilities.py deleted file mode 100644 index 15c47d5c92..0000000000 --- a/src/python/grpcio/grpc/framework/alpha/_face_utilities.py +++ /dev/null @@ -1,183 +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. - -import abc -import collections - -import six - -# face_interfaces is referenced from specification in this module. -from grpc.framework.common import cardinality -from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import -from grpc.framework.face import utilities as face_utilities -from grpc.framework.alpha import _reexport -from grpc.framework.alpha import interfaces - - -def _qualified_name(service_name, method_name): - return '/%s/%s' % (service_name, method_name) - - -# TODO(nathaniel): This structure is getting bloated; it could be shrunk if -# implementations._Stub used a generic rather than a dynamic underlying -# face-layer stub. -class InvocationBreakdown(six.with_metaclass(abc.ABCMeta)): - """An intermediate representation of invocation-side views of RPC methods. - - Attributes: - cardinalities: A dictionary from RPC method name to interfaces.Cardinality - value. - qualified_names: A dictionary from unqualified RPC method name to - service-qualified RPC method name. - face_cardinalities: A dictionary from service-qualified RPC method name to - to cardinality.Cardinality value. - request_serializers: A dictionary from service-qualified RPC method name to - callable behavior to be used serializing request values for the RPC. - response_deserializers: A dictionary from service-qualified RPC method name - to callable behavior to be used deserializing response values for the - RPC. - """ - - -class _EasyInvocationBreakdown( - InvocationBreakdown, - collections.namedtuple( - '_EasyInvocationBreakdown', - ('cardinalities', 'qualified_names', 'face_cardinalities', - 'request_serializers', 'response_deserializers'))): - pass - - -class ServiceBreakdown(six.with_metaclass(abc.ABCMeta)): - """An intermediate representation of service-side views of RPC methods. - - Attributes: - implementations: A dictionary from service-qualified RPC method name to - face_interfaces.MethodImplementation implementing the RPC method. - request_deserializers: A dictionary from service-qualified RPC method name - to callable behavior to be used deserializing request values for the RPC. - response_serializers: A dictionary from service-qualified RPC method name - to callable behavior to be used serializing response values for the RPC. - """ - - -class _EasyServiceBreakdown( - ServiceBreakdown, - collections.namedtuple( - '_EasyServiceBreakdown', - ('implementations', 'request_deserializers', 'response_serializers'))): - pass - - -def break_down_invocation(service_name, method_descriptions): - """Derives an InvocationBreakdown from several RPC method descriptions. - - Args: - service_name: The package-qualified full name of the service. - method_descriptions: A dictionary from RPC method name to - interfaces.RpcMethodInvocationDescription describing the RPCs. - - Returns: - An InvocationBreakdown corresponding to the given method descriptions. - """ - cardinalities = {} - qualified_names = {} - face_cardinalities = {} - request_serializers = {} - response_deserializers = {} - for name, method_description in six.iteritems(method_descriptions): - qualified_name = _qualified_name(service_name, name) - method_cardinality = method_description.cardinality() - cardinalities[name] = method_description.cardinality() - qualified_names[name] = qualified_name - face_cardinalities[qualified_name] = _reexport.common_cardinality( - method_cardinality) - request_serializers[qualified_name] = method_description.serialize_request - response_deserializers[qualified_name] = ( - method_description.deserialize_response) - return _EasyInvocationBreakdown( - cardinalities, qualified_names, face_cardinalities, request_serializers, - response_deserializers) - - -def break_down_service(service_name, method_descriptions): - """Derives a ServiceBreakdown from several RPC method descriptions. - - Args: - method_descriptions: A dictionary from RPC method name to - interfaces.RpcMethodServiceDescription describing the RPCs. - - Returns: - A ServiceBreakdown corresponding to the given method descriptions. - """ - implementations = {} - request_deserializers = {} - response_serializers = {} - for name, method_description in six.iteritems(method_descriptions): - qualified_name = _qualified_name(service_name, name) - method_cardinality = method_description.cardinality() - if method_cardinality is interfaces.Cardinality.UNARY_UNARY: - def service( - request, face_rpc_context, - service_behavior=method_description.service_unary_unary): - return service_behavior( - request, _reexport.rpc_context(face_rpc_context)) - implementations[qualified_name] = face_utilities.unary_unary_inline( - service) - elif method_cardinality is interfaces.Cardinality.UNARY_STREAM: - def service( - request, face_rpc_context, - service_behavior=method_description.service_unary_stream): - return service_behavior( - request, _reexport.rpc_context(face_rpc_context)) - implementations[qualified_name] = face_utilities.unary_stream_inline( - service) - elif method_cardinality is interfaces.Cardinality.STREAM_UNARY: - def service( - request_iterator, face_rpc_context, - service_behavior=method_description.service_stream_unary): - return service_behavior( - request_iterator, _reexport.rpc_context(face_rpc_context)) - implementations[qualified_name] = face_utilities.stream_unary_inline( - service) - elif method_cardinality is interfaces.Cardinality.STREAM_STREAM: - def service( - request_iterator, face_rpc_context, - service_behavior=method_description.service_stream_stream): - return service_behavior( - request_iterator, _reexport.rpc_context(face_rpc_context)) - implementations[qualified_name] = face_utilities.stream_stream_inline( - service) - request_deserializers[qualified_name] = ( - method_description.deserialize_request) - response_serializers[qualified_name] = ( - method_description.serialize_response) - - return _EasyServiceBreakdown( - implementations, request_deserializers, response_serializers) diff --git a/src/python/grpcio/grpc/framework/alpha/_reexport.py b/src/python/grpcio/grpc/framework/alpha/_reexport.py deleted file mode 100644 index e027077a77..0000000000 --- a/src/python/grpcio/grpc/framework/alpha/_reexport.py +++ /dev/null @@ -1,205 +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. - -import six - -from grpc.framework.common import cardinality -from grpc.framework.face import exceptions as face_exceptions -from grpc.framework.face import interfaces as face_interfaces -from grpc.framework.foundation import future -from grpc.framework.alpha import exceptions -from grpc.framework.alpha import interfaces - -_EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY = { - interfaces.Cardinality.UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY, - interfaces.Cardinality.UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM, - interfaces.Cardinality.STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY, - interfaces.Cardinality.STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, -} - -_ABORTION_REEXPORT = { - face_interfaces.Abortion.CANCELLED: interfaces.Abortion.CANCELLED, - face_interfaces.Abortion.EXPIRED: interfaces.Abortion.EXPIRED, - face_interfaces.Abortion.NETWORK_FAILURE: - interfaces.Abortion.NETWORK_FAILURE, - face_interfaces.Abortion.SERVICED_FAILURE: - interfaces.Abortion.SERVICED_FAILURE, - face_interfaces.Abortion.SERVICER_FAILURE: - interfaces.Abortion.SERVICER_FAILURE, -} - - -class _RpcError(exceptions.RpcError): - pass - - -def _reexport_error(face_rpc_error): - if isinstance(face_rpc_error, face_exceptions.CancellationError): - return exceptions.CancellationError() - elif isinstance(face_rpc_error, face_exceptions.ExpirationError): - return exceptions.ExpirationError() - else: - return _RpcError() - - -def _as_face_abortion_callback(abortion_callback): - def face_abortion_callback(face_abortion): - abortion_callback(_ABORTION_REEXPORT[face_abortion]) - return face_abortion_callback - - -class _ReexportedFuture(future.Future): - - def __init__(self, face_future): - self._face_future = face_future - - def cancel(self): - return self._face_future.cancel() - - def cancelled(self): - return self._face_future.cancelled() - - def running(self): - return self._face_future.running() - - def done(self): - return self._face_future.done() - - def result(self, timeout=None): - try: - return self._face_future.result(timeout=timeout) - except face_exceptions.RpcError as e: - raise _reexport_error(e) - - def exception(self, timeout=None): - face_error = self._face_future.exception(timeout=timeout) - return None if face_error is None else _reexport_error(face_error) - - def traceback(self, timeout=None): - return self._face_future.traceback(timeout=timeout) - - def add_done_callback(self, fn): - self._face_future.add_done_callback(lambda unused_face_future: fn(self)) - - -def _call_reexporting_errors(behavior, *args, **kwargs): - try: - return behavior(*args, **kwargs) - except face_exceptions.RpcError as e: - raise _reexport_error(e) - - -def _reexported_future(face_future): - return _ReexportedFuture(face_future) - - -class _CancellableIterator(interfaces.CancellableIterator): - - def __init__(self, face_cancellable_iterator): - self._face_cancellable_iterator = face_cancellable_iterator - - def __iter__(self): - return self - - def next(self): - return _call_reexporting_errors(self._face_cancellable_iterator.next) - - def cancel(self): - self._face_cancellable_iterator.cancel() - - -class _RpcContext(interfaces.RpcContext): - - def __init__(self, face_rpc_context): - self._face_rpc_context = face_rpc_context - - def is_active(self): - return self._face_rpc_context.is_active() - - def time_remaining(self): - return self._face_rpc_context.time_remaining() - - def add_abortion_callback(self, abortion_callback): - self._face_rpc_context.add_abortion_callback( - _as_face_abortion_callback(abortion_callback)) - - -class _UnaryUnarySyncAsync(interfaces.UnaryUnarySyncAsync): - - def __init__(self, face_unary_unary_multi_callable): - self._underlying = face_unary_unary_multi_callable - - def __call__(self, request, timeout): - return _call_reexporting_errors( - self._underlying, request, timeout) - - def async(self, request, timeout): - return _ReexportedFuture(self._underlying.future(request, timeout)) - - -class _StreamUnarySyncAsync(interfaces.StreamUnarySyncAsync): - - def __init__(self, face_stream_unary_multi_callable): - self._underlying = face_stream_unary_multi_callable - - def __call__(self, request_iterator, timeout): - return _call_reexporting_errors( - self._underlying, request_iterator, timeout) - - def async(self, request_iterator, timeout): - return _ReexportedFuture(self._underlying.future(request_iterator, timeout)) - - -def common_cardinality(early_adopter_cardinality): - return _EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY[ - early_adopter_cardinality] - - -def common_cardinalities(early_adopter_cardinalities): - common_cardinalities = {} - for name, early_adopter_cardinality in six.iteritems(early_adopter_cardinalities): - common_cardinalities[name] = _EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY[ - early_adopter_cardinality] - return common_cardinalities - - -def rpc_context(face_rpc_context): - return _RpcContext(face_rpc_context) - - -def cancellable_iterator(face_cancellable_iterator): - return _CancellableIterator(face_cancellable_iterator) - - -def unary_unary_sync_async(face_unary_unary_multi_callable): - return _UnaryUnarySyncAsync(face_unary_unary_multi_callable) - - -def stream_unary_sync_async(face_stream_unary_multi_callable): - return _StreamUnarySyncAsync(face_stream_unary_multi_callable) diff --git a/src/python/grpcio/grpc/framework/alpha/exceptions.py b/src/python/grpcio/grpc/framework/alpha/exceptions.py deleted file mode 100644 index 09359c5e94..0000000000 --- a/src/python/grpcio/grpc/framework/alpha/exceptions.py +++ /dev/null @@ -1,47 +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. - -"""Exceptions raised by GRPC. - -Only GRPC should instantiate and raise these exceptions. -""" -import abc - -import six - -class RpcError(six.with_metaclass(abc.ABCMeta, Exception)): - """Common super type for all exceptions raised by GRPC.""" - - -class CancellationError(RpcError): - """Indicates that an RPC has been cancelled.""" - - -class ExpirationError(RpcError): - """Indicates that an RPC has expired ("timed out").""" diff --git a/src/python/grpcio/grpc/framework/alpha/interfaces.py b/src/python/grpcio/grpc/framework/alpha/interfaces.py deleted file mode 100644 index 48f144f614..0000000000 --- a/src/python/grpcio/grpc/framework/alpha/interfaces.py +++ /dev/null @@ -1,384 +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. - -"""Interfaces of GRPC.""" - -import abc -import enum - -import six - -# exceptions is referenced from specification in this module. -from grpc.framework.alpha import exceptions # pylint: disable=unused-import -from grpc.framework.foundation import activated -from grpc.framework.foundation import future - - -@enum.unique -class Cardinality(enum.Enum): - """Constants for the four cardinalities of RPC.""" - - UNARY_UNARY = 'request-unary/response-unary' - UNARY_STREAM = 'request-unary/response-streaming' - STREAM_UNARY = 'request-streaming/response-unary' - STREAM_STREAM = 'request-streaming/response-streaming' - - -@enum.unique -class Abortion(enum.Enum): - """Categories of RPC abortion.""" - - CANCELLED = 'cancelled' - EXPIRED = 'expired' - NETWORK_FAILURE = 'network failure' - SERVICED_FAILURE = 'serviced failure' - SERVICER_FAILURE = 'servicer failure' - - -class CancellableIterator(six.with_metaclass(abc.ABCMeta)): - """Implements the Iterator protocol and affords a cancel method.""" - - @abc.abstractmethod - def __iter__(self): - """Returns the self object in accordance with the Iterator protocol.""" - raise NotImplementedError() - - def __next__(self): - return self.next() - - @abc.abstractmethod - def next(self): - """Returns a value or raises StopIteration per the Iterator protocol.""" - raise NotImplementedError() - - @abc.abstractmethod - def cancel(self): - """Requests cancellation of whatever computation underlies this iterator.""" - raise NotImplementedError() - - -class RpcContext(six.with_metaclass(abc.ABCMeta)): - """Provides RPC-related information and action.""" - - @abc.abstractmethod - def is_active(self): - """Describes whether the RPC is active or has terminated.""" - raise NotImplementedError() - - @abc.abstractmethod - def time_remaining(self): - """Describes the length of allowed time remaining for the RPC. - Returns: - A nonnegative float indicating the length of allowed time in seconds - remaining for the RPC to complete before it is considered to have timed - out. - """ - raise NotImplementedError() - - @abc.abstractmethod - def add_abortion_callback(self, abortion_callback): - """Registers a callback to be called if the RPC is aborted. - Args: - abortion_callback: A callable to be called and passed an Abortion value - in the event of RPC abortion. - """ - raise NotImplementedError() - - -class UnaryUnarySyncAsync(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a unary-unary RPC synchronously or asynchronously. - Values implementing this interface are directly callable and present an - "async" method. Both calls take a request value and a numeric timeout. - Direct invocation of a value of this type invokes its associated RPC and - blocks until the RPC's response is available. Calling the "async" method - of a value of this type invokes its associated RPC and immediately returns a - future.Future bound to the asynchronous execution of the RPC. - """ - - @abc.abstractmethod - def __call__(self, request, timeout): - """Synchronously invokes the underlying RPC. - Args: - request: The request value for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - Returns: - The response value for the RPC. - Raises: - exceptions.RpcError: Indicating that the RPC was aborted. - """ - raise NotImplementedError() - - @abc.abstractmethod - def async(self, request, timeout): - """Asynchronously invokes the underlying RPC. - Args: - request: The request value for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - Returns: - A future.Future representing the RPC. In the event of RPC completion, the - returned Future's result value will be the response value of the RPC. - In the event of RPC abortion, the returned Future's exception value - will be an exceptions.RpcError. - """ - raise NotImplementedError() - - -class StreamUnarySyncAsync(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a stream-unary RPC synchronously or asynchronously. - Values implementing this interface are directly callable and present an - "async" method. Both calls take an iterator of request values and a numeric - timeout. Direct invocation of a value of this type invokes its associated RPC - and blocks until the RPC's response is available. Calling the "async" method - of a value of this type invokes its associated RPC and immediately returns a - future.Future bound to the asynchronous execution of the RPC. - """ - - @abc.abstractmethod - def __call__(self, request_iterator, timeout): - """Synchronously invokes the underlying RPC. - - Args: - request_iterator: An iterator that yields request values for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - The response value for the RPC. - - Raises: - exceptions.RpcError: Indicating that the RPC was aborted. - """ - raise NotImplementedError() - - @abc.abstractmethod - def async(self, request_iterator, timeout): - """Asynchronously invokes the underlying RPC. - - Args: - request_iterator: An iterator that yields request values for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A future.Future representing the RPC. In the event of RPC completion, the - returned Future's result value will be the response value of the RPC. - In the event of RPC abortion, the returned Future's exception value - will be an exceptions.RpcError. - """ - raise NotImplementedError() - - -class RpcMethodDescription(six.with_metaclass(abc.ABCMeta)): - """A type for the common aspects of RPC method descriptions.""" - - @abc.abstractmethod - def cardinality(self): - """Identifies the cardinality of this RpcMethodDescription. - - Returns: - A Cardinality value identifying whether or not this - RpcMethodDescription is request-unary or request-streaming and - whether or not it is response-unary or response-streaming. - """ - raise NotImplementedError() - - -class RpcMethodInvocationDescription(six.with_metaclass(abc.ABCMeta, RpcMethodDescription)): - """Invocation-side description of an RPC method.""" - - @abc.abstractmethod - def serialize_request(self, request): - """Serializes a request value. - - Args: - request: A request value appropriate for the RPC method described by this - RpcMethodInvocationDescription. - - Returns: - The serialization of the given request value as a - bytestring. - """ - raise NotImplementedError() - - @abc.abstractmethod - def deserialize_response(self, serialized_response): - """Deserializes a response value. - - Args: - serialized_response: A bytestring that is the serialization of a response - value appropriate for the RPC method described by this - RpcMethodInvocationDescription. - - Returns: - A response value corresponding to the given bytestring. - """ - raise NotImplementedError() - - -class RpcMethodServiceDescription(six.with_metaclass(abc.ABCMeta, RpcMethodDescription)): - """Service-side description of an RPC method.""" - - @abc.abstractmethod - def deserialize_request(self, serialized_request): - """Deserializes a request value. - - Args: - serialized_request: A bytestring that is the serialization of a request - value appropriate for the RPC method described by this - RpcMethodServiceDescription. - - Returns: - A request value corresponding to the given bytestring. - """ - raise NotImplementedError() - - @abc.abstractmethod - def serialize_response(self, response): - """Serializes a response value. - - Args: - response: A response value appropriate for the RPC method described by - this RpcMethodServiceDescription. - - Returns: - The serialization of the given response value as a - bytestring. - """ - raise NotImplementedError() - - @abc.abstractmethod - def service_unary_unary(self, request, context): - """Carries out this RPC. - - This method may only be called if the cardinality of this - RpcMethodServiceDescription is Cardinality.UNARY_UNARY. - - Args: - request: A request value appropriate for the RPC method described by this - RpcMethodServiceDescription. - context: An RpcContext object for the RPC. - - Returns: - A response value appropriate for the RPC method described by this - RpcMethodServiceDescription. - """ - raise NotImplementedError() - - @abc.abstractmethod - def service_unary_stream(self, request, context): - """Carries out this RPC. - - This method may only be called if the cardinality of this - RpcMethodServiceDescription is Cardinality.UNARY_STREAM. - - Args: - request: A request value appropriate for the RPC method described by this - RpcMethodServiceDescription. - context: An RpcContext object for the RPC. - - Yields: - Zero or more response values appropriate for the RPC method described by - this RpcMethodServiceDescription. - """ - raise NotImplementedError() - - @abc.abstractmethod - def service_stream_unary(self, request_iterator, context): - """Carries out this RPC. - - This method may only be called if the cardinality of this - RpcMethodServiceDescription is Cardinality.STREAM_UNARY. - - Args: - request_iterator: An iterator of request values appropriate for the RPC - method described by this RpcMethodServiceDescription. - context: An RpcContext object for the RPC. - - Returns: - A response value appropriate for the RPC method described by this - RpcMethodServiceDescription. - """ - raise NotImplementedError() - - @abc.abstractmethod - def service_stream_stream(self, request_iterator, context): - """Carries out this RPC. - - This method may only be called if the cardinality of this - RpcMethodServiceDescription is Cardinality.STREAM_STREAM. - - Args: - request_iterator: An iterator of request values appropriate for the RPC - method described by this RpcMethodServiceDescription. - context: An RpcContext object for the RPC. - - Yields: - Zero or more response values appropriate for the RPC method described by - this RpcMethodServiceDescription. - """ - raise NotImplementedError() - - -class Stub(six.with_metaclass(abc.ABCMeta)): - """A stub with callable RPC method names for attributes. - - Instances of this type are context managers and only afford RPC invocation - when used in context. - - Instances of this type, when used in context, respond to attribute access - as follows: if the requested attribute is the name of a unary-unary RPC - method, the value of the attribute will be a UnaryUnarySyncAsync with which - to invoke the RPC method. If the requested attribute is the name of a - unary-stream RPC method, the value of the attribute will be a callable taking - a request object and a timeout parameter and returning a CancellableIterator - that yields the response values of the RPC. If the requested attribute is the - name of a stream-unary RPC method, the value of the attribute will be a - StreamUnarySyncAsync with which to invoke the RPC method. If the requested - attribute is the name of a stream-stream RPC method, the value of the - attribute will be a callable taking an iterator of request objects and a - timeout and returning a CancellableIterator that yields the response values - of the RPC. - - In all cases indication of abortion is indicated by raising of - exceptions.RpcError, exceptions.CancellationError, - and exceptions.ExpirationError. - """ - - -class Server(six.with_metaclass(abc.ABCMeta, activated.Activated)): - """A GRPC Server.""" - - @abc.abstractmethod - def port(self): - """Reports the port on which the server is serving. - - This method may only be called while the server is activated. - - Returns: - The port on which the server is serving. - """ - raise NotImplementedError() diff --git a/src/python/grpcio/grpc/framework/alpha/utilities.py b/src/python/grpcio/grpc/framework/alpha/utilities.py deleted file mode 100644 index 7d7f78f5e4..0000000000 --- a/src/python/grpcio/grpc/framework/alpha/utilities.py +++ /dev/null @@ -1,269 +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. - -"""Utilities for use with GRPC.""" - -from grpc.framework.alpha import interfaces - - -class _RpcMethodDescription( - interfaces.RpcMethodInvocationDescription, - interfaces.RpcMethodServiceDescription): - - def __init__( - self, cardinality, unary_unary, unary_stream, stream_unary, - stream_stream, request_serializer, request_deserializer, - response_serializer, response_deserializer): - self._cardinality = cardinality - self._unary_unary = unary_unary - self._unary_stream = unary_stream - self._stream_unary = stream_unary - self._stream_stream = stream_stream - self._request_serializer = request_serializer - self._request_deserializer = request_deserializer - self._response_serializer = response_serializer - self._response_deserializer = response_deserializer - - def cardinality(self): - """See interfaces.RpcMethodDescription.cardinality for specification.""" - return self._cardinality - - def serialize_request(self, request): - """See interfaces.RpcMethodInvocationDescription.serialize_request.""" - return self._request_serializer(request) - - def deserialize_request(self, serialized_request): - """See interfaces.RpcMethodServiceDescription.deserialize_request.""" - return self._request_deserializer(serialized_request) - - def serialize_response(self, response): - """See interfaces.RpcMethodServiceDescription.serialize_response.""" - return self._response_serializer(response) - - def deserialize_response(self, serialized_response): - """See interfaces.RpcMethodInvocationDescription.deserialize_response.""" - return self._response_deserializer(serialized_response) - - def service_unary_unary(self, request, context): - """See interfaces.RpcMethodServiceDescription.service_unary_unary.""" - return self._unary_unary(request, context) - - def service_unary_stream(self, request, context): - """See interfaces.RpcMethodServiceDescription.service_unary_stream.""" - return self._unary_stream(request, context) - - def service_stream_unary(self, request_iterator, context): - """See interfaces.RpcMethodServiceDescription.service_stream_unary.""" - return self._stream_unary(request_iterator, context) - - def service_stream_stream(self, request_iterator, context): - """See interfaces.RpcMethodServiceDescription.service_stream_stream.""" - return self._stream_stream(request_iterator, context) - - -def unary_unary_invocation_description( - request_serializer, response_deserializer): - """Creates an interfaces.RpcMethodInvocationDescription for an RPC method. - - Args: - request_serializer: A callable that when called on a request - value returns a bytestring corresponding to that value. - response_deserializer: A callable that when called on a - bytestring returns the response value corresponding to - that bytestring. - - Returns: - An interfaces.RpcMethodInvocationDescription constructed from the given - arguments representing a unary-request/unary-response RPC method. - """ - return _RpcMethodDescription( - interfaces.Cardinality.UNARY_UNARY, None, None, None, None, - request_serializer, None, None, response_deserializer) - - -def unary_stream_invocation_description( - request_serializer, response_deserializer): - """Creates an interfaces.RpcMethodInvocationDescription for an RPC method. - - Args: - request_serializer: A callable that when called on a request - value returns a bytestring corresponding to that value. - response_deserializer: A callable that when called on a - bytestring returns the response value corresponding to - that bytestring. - - Returns: - An interfaces.RpcMethodInvocationDescription constructed from the given - arguments representing a unary-request/streaming-response RPC method. - """ - return _RpcMethodDescription( - interfaces.Cardinality.UNARY_STREAM, None, None, None, None, - request_serializer, None, None, response_deserializer) - - -def stream_unary_invocation_description( - request_serializer, response_deserializer): - """Creates an interfaces.RpcMethodInvocationDescription for an RPC method. - - Args: - request_serializer: A callable that when called on a request - value returns a bytestring corresponding to that value. - response_deserializer: A callable that when called on a - bytestring returns the response value corresponding to - that bytestring. - - Returns: - An interfaces.RpcMethodInvocationDescription constructed from the given - arguments representing a streaming-request/unary-response RPC method. - """ - return _RpcMethodDescription( - interfaces.Cardinality.STREAM_UNARY, None, None, None, None, - request_serializer, None, None, response_deserializer) - - -def stream_stream_invocation_description( - request_serializer, response_deserializer): - """Creates an interfaces.RpcMethodInvocationDescription for an RPC method. - - Args: - request_serializer: A callable that when called on a request - value returns a bytestring corresponding to that value. - response_deserializer: A callable that when called on a - bytestring returns the response value corresponding to - that bytestring. - - Returns: - An interfaces.RpcMethodInvocationDescription constructed from the given - arguments representing a streaming-request/streaming-response RPC - method. - """ - return _RpcMethodDescription( - interfaces.Cardinality.STREAM_STREAM, None, None, None, None, - request_serializer, None, None, response_deserializer) - - -def unary_unary_service_description( - behavior, request_deserializer, response_serializer): - """Creates an interfaces.RpcMethodServiceDescription for the given behavior. - - Args: - behavior: A callable that implements a unary-unary RPC - method that accepts a single request and an interfaces.RpcContext and - returns a single response. - request_deserializer: A callable that when called on a - bytestring returns the request value corresponding to that - bytestring. - response_serializer: A callable that when called on a - response value returns the bytestring corresponding to - that value. - - Returns: - An interfaces.RpcMethodServiceDescription constructed from the given - arguments representing a unary-request/unary-response RPC - method. - """ - return _RpcMethodDescription( - interfaces.Cardinality.UNARY_UNARY, behavior, None, None, None, - None, request_deserializer, response_serializer, None) - - -def unary_stream_service_description( - behavior, request_deserializer, response_serializer): - """Creates an interfaces.RpcMethodServiceDescription for the given behavior. - - Args: - behavior: A callable that implements a unary-stream RPC - method that accepts a single request and an interfaces.RpcContext - and returns an iterator of zero or more responses. - request_deserializer: A callable that when called on a - bytestring returns the request value corresponding to that - bytestring. - response_serializer: A callable that when called on a - response value returns the bytestring corresponding to - that value. - - Returns: - An interfaces.RpcMethodServiceDescription constructed from the given - arguments representing a unary-request/streaming-response - RPC method. - """ - return _RpcMethodDescription( - interfaces.Cardinality.UNARY_STREAM, None, behavior, None, None, - None, request_deserializer, response_serializer, None) - - -def stream_unary_service_description( - behavior, request_deserializer, response_serializer): - """Creates an interfaces.RpcMethodServiceDescription for the given behavior. - - Args: - behavior: A callable that implements a stream-unary RPC - method that accepts an iterator of zero or more requests - and an interfaces.RpcContext and returns a single response. - request_deserializer: A callable that when called on a - bytestring returns the request value corresponding to that - bytestring. - response_serializer: A callable that when called on a - response value returns the bytestring corresponding to - that value. - - Returns: - An interfaces.RpcMethodServiceDescription constructed from the given - arguments representing a streaming-request/unary-response - RPC method. - """ - return _RpcMethodDescription( - interfaces.Cardinality.STREAM_UNARY, None, None, behavior, None, - None, request_deserializer, response_serializer, None) - - -def stream_stream_service_description( - behavior, request_deserializer, response_serializer): - """Creates an interfaces.RpcMethodServiceDescription for the given behavior. - - Args: - behavior: A callable that implements a stream-stream RPC - method that accepts an iterator of zero or more requests - and an interfaces.RpcContext and returns an iterator of - zero or more responses. - request_deserializer: A callable that when called on a - bytestring returns the request value corresponding to that - bytestring. - response_serializer: A callable that when called on a - response value returns the bytestring corresponding to - that value. - - Returns: - An interfaces.RpcMethodServiceDescription constructed from the given - arguments representing a - streaming-request/streaming-response RPC method. - """ - return _RpcMethodDescription( - interfaces.Cardinality.STREAM_STREAM, None, None, None, behavior, - None, request_deserializer, response_serializer, None) diff --git a/src/python/grpcio/grpc/framework/base/__init__.py b/src/python/grpcio/grpc/framework/base/__init__.py deleted file mode 100644 index bff74be2c7..0000000000 --- a/src/python/grpcio/grpc/framework/base/__init__.py +++ /dev/null @@ -1,35 +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. - -import warnings - -warnings.simplefilter('always', DeprecationWarning) -warnings.warn('the alpha API (includes this package) is deprecated, ' - 'unmaintained, and no longer tested. Please migrate to the beta ' - 'API.', DeprecationWarning, stacklevel=2) diff --git a/src/python/grpcio/grpc/framework/base/_cancellation.py b/src/python/grpcio/grpc/framework/base/_cancellation.py deleted file mode 100644 index ffbc90668f..0000000000 --- a/src/python/grpcio/grpc/framework/base/_cancellation.py +++ /dev/null @@ -1,64 +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. - -"""State and behavior for operation cancellation.""" - -from grpc.framework.base import _interfaces -from grpc.framework.base import interfaces - - -class CancellationManager(_interfaces.CancellationManager): - """An implementation of _interfaces.CancellationManager.""" - - def __init__( - self, lock, termination_manager, transmission_manager, ingestion_manager, - expiration_manager): - """Constructor. - - Args: - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - ingestion_manager: The _interfaces.IngestionManager for the operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - """ - self._lock = lock - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._ingestion_manager = ingestion_manager - self._expiration_manager = expiration_manager - - def cancel(self): - """See _interfaces.CancellationManager.cancel for specification.""" - with self._lock: - self._termination_manager.abort(interfaces.Outcome.CANCELLED) - self._transmission_manager.abort(interfaces.Outcome.CANCELLED) - self._ingestion_manager.abort() - self._expiration_manager.abort() diff --git a/src/python/grpcio/grpc/framework/base/_constants.py b/src/python/grpcio/grpc/framework/base/_constants.py deleted file mode 100644 index 8fbdc82782..0000000000 --- a/src/python/grpcio/grpc/framework/base/_constants.py +++ /dev/null @@ -1,32 +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. - -"""Private constants for the package.""" - -INTERNAL_ERROR_LOG_MESSAGE = ':-( RPC Framework (Base) internal error! :-(' diff --git a/src/python/grpcio/grpc/framework/base/_context.py b/src/python/grpcio/grpc/framework/base/_context.py deleted file mode 100644 index d84871d639..0000000000 --- a/src/python/grpcio/grpc/framework/base/_context.py +++ /dev/null @@ -1,99 +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. - -"""State and behavior for operation context.""" - -import time - -# _interfaces is referenced from specification in this module. -from grpc.framework.base import interfaces -from grpc.framework.base import _interfaces # pylint: disable=unused-import - - -class OperationContext(interfaces.OperationContext): - """An implementation of interfaces.OperationContext.""" - - def __init__( - self, lock, operation_id, local_failure, termination_manager, - transmission_manager): - """Constructor. - - Args: - lock: The operation-wide lock. - operation_id: An object identifying the operation. - local_failure: Whichever one of interfaces.Outcome.SERVICED_FAILURE or - interfaces.Outcome.SERVICER_FAILURE describes local failure of - customer code. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - """ - self._lock = lock - self._local_failure = local_failure - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._ingestion_manager = None - self._expiration_manager = None - - self.operation_id = operation_id - - def set_ingestion_and_expiration_managers( - self, ingestion_manager, expiration_manager): - """Sets managers with which this OperationContext cooperates. - - Args: - ingestion_manager: The _interfaces.IngestionManager for the operation. - expiration_manager: The _interfaces.ExpirationManager for the operation. - """ - self._ingestion_manager = ingestion_manager - self._expiration_manager = expiration_manager - - def is_active(self): - """See interfaces.OperationContext.is_active for specification.""" - with self._lock: - return self._termination_manager.is_active() - - def add_termination_callback(self, callback): - """See interfaces.OperationContext.add_termination_callback.""" - with self._lock: - self._termination_manager.add_callback(callback) - - def time_remaining(self): - """See interfaces.OperationContext.time_remaining for specification.""" - with self._lock: - deadline = self._expiration_manager.deadline() - return max(0.0, deadline - time.time()) - - def fail(self, exception): - """See interfaces.OperationContext.fail for specification.""" - with self._lock: - self._termination_manager.abort(self._local_failure) - self._transmission_manager.abort(self._local_failure) - self._ingestion_manager.abort() - self._expiration_manager.abort() diff --git a/src/python/grpcio/grpc/framework/base/_emission.py b/src/python/grpcio/grpc/framework/base/_emission.py deleted file mode 100644 index 1829669a72..0000000000 --- a/src/python/grpcio/grpc/framework/base/_emission.py +++ /dev/null @@ -1,125 +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. - -"""State and behavior for handling emitted values.""" - -from grpc.framework.base import interfaces -from grpc.framework.base import _interfaces - - -class _EmissionManager(_interfaces.EmissionManager): - """An implementation of _interfaces.EmissionManager.""" - - def __init__( - self, lock, failure_outcome, termination_manager, transmission_manager): - """Constructor. - - Args: - lock: The operation-wide lock. - failure_outcome: Whichever one of interfaces.Outcome.SERVICED_FAILURE or - interfaces.Outcome.SERVICER_FAILURE describes this object's methods - being called inappropriately by customer code. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - """ - self._lock = lock - self._failure_outcome = failure_outcome - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._ingestion_manager = None - self._expiration_manager = None - - self._emission_complete = False - - def set_ingestion_manager_and_expiration_manager( - self, ingestion_manager, expiration_manager): - self._ingestion_manager = ingestion_manager - self._expiration_manager = expiration_manager - - def _abort(self): - self._termination_manager.abort(self._failure_outcome) - self._transmission_manager.abort(self._failure_outcome) - self._ingestion_manager.abort() - self._expiration_manager.abort() - - def consume(self, value): - with self._lock: - if self._emission_complete: - self._abort() - else: - self._transmission_manager.inmit(value, False) - - def terminate(self): - with self._lock: - if not self._emission_complete: - self._termination_manager.emission_complete() - self._transmission_manager.inmit(None, True) - self._emission_complete = True - - def consume_and_terminate(self, value): - with self._lock: - if self._emission_complete: - self._abort() - else: - self._termination_manager.emission_complete() - self._transmission_manager.inmit(value, True) - self._emission_complete = True - - -def front_emission_manager(lock, termination_manager, transmission_manager): - """Creates an _interfaces.EmissionManager appropriate for front-side use. - - Args: - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the operation. - - Returns: - An _interfaces.EmissionManager appropriate for front-side use. - """ - return _EmissionManager( - lock, interfaces.Outcome.SERVICED_FAILURE, termination_manager, - transmission_manager) - - -def back_emission_manager(lock, termination_manager, transmission_manager): - """Creates an _interfaces.EmissionManager appropriate for back-side use. - - Args: - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the operation. - - Returns: - An _interfaces.EmissionManager appropriate for back-side use. - """ - return _EmissionManager( - lock, interfaces.Outcome.SERVICER_FAILURE, termination_manager, - transmission_manager) diff --git a/src/python/grpcio/grpc/framework/base/_ends.py b/src/python/grpcio/grpc/framework/base/_ends.py deleted file mode 100644 index 176f3ac06e..0000000000 --- a/src/python/grpcio/grpc/framework/base/_ends.py +++ /dev/null @@ -1,399 +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. - -"""Implementations of FrontLinks and BackLinks.""" - -import collections -import threading -import uuid - -# _interfaces is referenced from specification in this module. -from grpc.framework.base import _cancellation -from grpc.framework.base import _context -from grpc.framework.base import _emission -from grpc.framework.base import _expiration -from grpc.framework.base import _ingestion -from grpc.framework.base import _interfaces # pylint: disable=unused-import -from grpc.framework.base import _reception -from grpc.framework.base import _termination -from grpc.framework.base import _transmission -from grpc.framework.base import interfaces -from grpc.framework.foundation import callable_util - -_IDLE_ACTION_EXCEPTION_LOG_MESSAGE = 'Exception calling idle action!' - - -class _EasyOperation(interfaces.Operation): - """A trivial implementation of interfaces.Operation.""" - - def __init__(self, emission_manager, context, cancellation_manager): - """Constructor. - - Args: - emission_manager: The _interfaces.EmissionManager for the operation that - will accept values emitted by customer code. - context: The interfaces.OperationContext for use by the customer - during the operation. - cancellation_manager: The _interfaces.CancellationManager for the - operation. - """ - self.consumer = emission_manager - self.context = context - self._cancellation_manager = cancellation_manager - - def cancel(self): - self._cancellation_manager.cancel() - - -class _Endlette(object): - """Utility for stateful behavior common to Fronts and Backs.""" - - def __init__(self, pool): - """Constructor. - - Args: - pool: A thread pool to use when calling registered idle actions. - """ - self._lock = threading.Lock() - self._pool = pool - # Dictionary from operation IDs to ReceptionManager-or-None. A None value - # indicates an in-progress fire-and-forget operation for which the customer - # has chosen to ignore results. - self._operations = {} - self._stats = {outcome: 0 for outcome in interfaces.Outcome} - self._idle_actions = [] - - def terminal_action(self, operation_id): - """Constructs the termination action for a single operation. - - Args: - operation_id: An operation ID. - - Returns: - A callable that takes an operation outcome for an argument to be used as - the termination action for the operation associated with the given - operation ID. - """ - def termination_action(outcome): - with self._lock: - self._stats[outcome] += 1 - self._operations.pop(operation_id, None) - if not self._operations: - for action in self._idle_actions: - self._pool.submit(callable_util.with_exceptions_logged( - action, _IDLE_ACTION_EXCEPTION_LOG_MESSAGE)) - self._idle_actions = [] - return termination_action - - def __enter__(self): - self._lock.acquire() - - def __exit__(self, exc_type, exc_val, exc_tb): - self._lock.release() - - def get_operation(self, operation_id): - return self._operations.get(operation_id, None) - - def add_operation(self, operation_id, operation_reception_manager): - self._operations[operation_id] = operation_reception_manager - - def operation_stats(self): - with self._lock: - return dict(self._stats) - - def add_idle_action(self, action): - with self._lock: - if self._operations: - self._idle_actions.append(action) - else: - self._pool.submit(callable_util.with_exceptions_logged( - action, _IDLE_ACTION_EXCEPTION_LOG_MESSAGE)) - - -class _FrontManagement( - collections.namedtuple( - '_FrontManagement', - ('reception', 'emission', 'operation', 'cancellation'))): - """Just a trivial helper class to bundle four fellow-traveling objects.""" - - -def _front_operate( - callback, work_pool, transmission_pool, utility_pool, - termination_action, operation_id, name, payload, complete, timeout, - subscription, trace_id): - """Constructs objects necessary for front-side operation management. - - Args: - callback: A callable that accepts interfaces.FrontToBackTickets and - delivers them to the other side of the operation. Execution of this - callable may take any arbitrary length of time. - work_pool: A thread pool in which to execute customer code. - transmission_pool: A thread pool to use for transmitting to the other side - of the operation. - utility_pool: A thread pool for utility tasks. - termination_action: A no-arg behavior to be called upon operation - completion. - operation_id: An object identifying the operation. - name: The name of the method being called during the operation. - payload: The first customer-significant value to be transmitted to the other - side. May be None if there is no such value or if the customer chose not - to pass it at operation invocation. - complete: A boolean indicating whether or not additional payloads will be - supplied by the customer. - timeout: A length of time in seconds to allow for the operation. - subscription: A interfaces.ServicedSubscription describing the - customer's interest in the results of the operation. - trace_id: A uuid.UUID identifying a set of related operations to which this - operation belongs. May be None. - - Returns: - A _FrontManagement object bundling together the - _interfaces.ReceptionManager, _interfaces.EmissionManager, - _context.OperationContext, and _interfaces.CancellationManager for the - operation. - """ - lock = threading.Lock() - with lock: - termination_manager = _termination.front_termination_manager( - work_pool, utility_pool, termination_action, subscription.kind) - transmission_manager = _transmission.front_transmission_manager( - lock, transmission_pool, callback, operation_id, name, - subscription.kind, trace_id, timeout, termination_manager) - operation_context = _context.OperationContext( - lock, operation_id, interfaces.Outcome.SERVICED_FAILURE, - termination_manager, transmission_manager) - emission_manager = _emission.front_emission_manager( - lock, termination_manager, transmission_manager) - ingestion_manager = _ingestion.front_ingestion_manager( - lock, work_pool, subscription, termination_manager, - transmission_manager, operation_context) - expiration_manager = _expiration.front_expiration_manager( - lock, termination_manager, transmission_manager, ingestion_manager, - timeout) - reception_manager = _reception.front_reception_manager( - lock, termination_manager, transmission_manager, ingestion_manager, - expiration_manager) - cancellation_manager = _cancellation.CancellationManager( - lock, termination_manager, transmission_manager, ingestion_manager, - expiration_manager) - - termination_manager.set_expiration_manager(expiration_manager) - transmission_manager.set_ingestion_and_expiration_managers( - ingestion_manager, expiration_manager) - operation_context.set_ingestion_and_expiration_managers( - ingestion_manager, expiration_manager) - emission_manager.set_ingestion_manager_and_expiration_manager( - ingestion_manager, expiration_manager) - ingestion_manager.set_expiration_manager(expiration_manager) - - transmission_manager.inmit(payload, complete) - - if subscription.kind is interfaces.ServicedSubscription.Kind.NONE: - returned_reception_manager = None - else: - returned_reception_manager = reception_manager - - return _FrontManagement( - returned_reception_manager, emission_manager, operation_context, - cancellation_manager) - - -class FrontLink(interfaces.FrontLink): - """An implementation of interfaces.FrontLink.""" - - def __init__(self, work_pool, transmission_pool, utility_pool): - """Constructor. - - Args: - work_pool: A thread pool to be used for executing customer code. - transmission_pool: A thread pool to be used for transmitting values to - the other side of the operation. - utility_pool: A thread pool to be used for utility tasks. - """ - self._endlette = _Endlette(utility_pool) - self._work_pool = work_pool - self._transmission_pool = transmission_pool - self._utility_pool = utility_pool - self._callback = None - - self._operations = {} - - def join_rear_link(self, rear_link): - """See interfaces.ForeLink.join_rear_link for specification.""" - with self._endlette: - self._callback = rear_link.accept_front_to_back_ticket - - def operation_stats(self): - """See interfaces.End.operation_stats for specification.""" - return self._endlette.operation_stats() - - def add_idle_action(self, action): - """See interfaces.End.add_idle_action for specification.""" - self._endlette.add_idle_action(action) - - def operate( - self, name, payload, complete, timeout, subscription, trace_id): - """See interfaces.Front.operate for specification.""" - operation_id = uuid.uuid4() - with self._endlette: - management = _front_operate( - self._callback, self._work_pool, self._transmission_pool, - self._utility_pool, self._endlette.terminal_action(operation_id), - operation_id, name, payload, complete, timeout, subscription, - trace_id) - self._endlette.add_operation(operation_id, management.reception) - return _EasyOperation( - management.emission, management.operation, management.cancellation) - - def accept_back_to_front_ticket(self, ticket): - """See interfaces.End.act for specification.""" - with self._endlette: - reception_manager = self._endlette.get_operation(ticket.operation_id) - if reception_manager: - reception_manager.receive_ticket(ticket) - - -def _back_operate( - servicer, callback, work_pool, transmission_pool, utility_pool, - termination_action, ticket, default_timeout, maximum_timeout): - """Constructs objects necessary for back-side operation management. - - Also begins back-side operation by feeding the first received ticket into the - constructed _interfaces.ReceptionManager. - - Args: - servicer: An interfaces.Servicer for servicing operations. - callback: A callable that accepts interfaces.BackToFrontTickets and - delivers them to the other side of the operation. Execution of this - callable may take any arbitrary length of time. - work_pool: A thread pool in which to execute customer code. - transmission_pool: A thread pool to use for transmitting to the other side - of the operation. - utility_pool: A thread pool for utility tasks. - termination_action: A no-arg behavior to be called upon operation - completion. - ticket: The first interfaces.FrontToBackTicket received for the operation. - default_timeout: A length of time in seconds to be used as the default - time alloted for a single operation. - maximum_timeout: A length of time in seconds to be used as the maximum - time alloted for a single operation. - - Returns: - The _interfaces.ReceptionManager to be used for the operation. - """ - lock = threading.Lock() - with lock: - termination_manager = _termination.back_termination_manager( - work_pool, utility_pool, termination_action, ticket.subscription) - transmission_manager = _transmission.back_transmission_manager( - lock, transmission_pool, callback, ticket.operation_id, - termination_manager, ticket.subscription) - operation_context = _context.OperationContext( - lock, ticket.operation_id, interfaces.Outcome.SERVICER_FAILURE, - termination_manager, transmission_manager) - emission_manager = _emission.back_emission_manager( - lock, termination_manager, transmission_manager) - ingestion_manager = _ingestion.back_ingestion_manager( - lock, work_pool, servicer, termination_manager, - transmission_manager, operation_context, emission_manager) - expiration_manager = _expiration.back_expiration_manager( - lock, termination_manager, transmission_manager, ingestion_manager, - ticket.timeout, default_timeout, maximum_timeout) - reception_manager = _reception.back_reception_manager( - lock, termination_manager, transmission_manager, ingestion_manager, - expiration_manager) - - termination_manager.set_expiration_manager(expiration_manager) - transmission_manager.set_ingestion_and_expiration_managers( - ingestion_manager, expiration_manager) - operation_context.set_ingestion_and_expiration_managers( - ingestion_manager, expiration_manager) - emission_manager.set_ingestion_manager_and_expiration_manager( - ingestion_manager, expiration_manager) - ingestion_manager.set_expiration_manager(expiration_manager) - - reception_manager.receive_ticket(ticket) - - return reception_manager - - -class BackLink(interfaces.BackLink): - """An implementation of interfaces.BackLink.""" - - def __init__( - self, servicer, work_pool, transmission_pool, utility_pool, - default_timeout, maximum_timeout): - """Constructor. - - Args: - servicer: An interfaces.Servicer for servicing operations. - work_pool: A thread pool in which to execute customer code. - transmission_pool: A thread pool to use for transmitting to the other side - of the operation. - utility_pool: A thread pool for utility tasks. - default_timeout: A length of time in seconds to be used as the default - time alloted for a single operation. - maximum_timeout: A length of time in seconds to be used as the maximum - time alloted for a single operation. - """ - self._endlette = _Endlette(utility_pool) - self._servicer = servicer - self._work_pool = work_pool - self._transmission_pool = transmission_pool - self._utility_pool = utility_pool - self._default_timeout = default_timeout - self._maximum_timeout = maximum_timeout - self._callback = None - - def join_fore_link(self, fore_link): - """See interfaces.RearLink.join_fore_link for specification.""" - with self._endlette: - self._callback = fore_link.accept_back_to_front_ticket - - def accept_front_to_back_ticket(self, ticket): - """See interfaces.RearLink.accept_front_to_back_ticket for specification.""" - with self._endlette: - reception_manager = self._endlette.get_operation(ticket.operation_id) - if reception_manager is None: - reception_manager = _back_operate( - self._servicer, self._callback, self._work_pool, - self._transmission_pool, self._utility_pool, - self._endlette.terminal_action(ticket.operation_id), ticket, - self._default_timeout, self._maximum_timeout) - self._endlette.add_operation(ticket.operation_id, reception_manager) - else: - reception_manager.receive_ticket(ticket) - - def operation_stats(self): - """See interfaces.End.operation_stats for specification.""" - return self._endlette.operation_stats() - - def add_idle_action(self, action): - """See interfaces.End.add_idle_action for specification.""" - self._endlette.add_idle_action(action) diff --git a/src/python/grpcio/grpc/framework/base/_expiration.py b/src/python/grpcio/grpc/framework/base/_expiration.py deleted file mode 100644 index 17acbef4c1..0000000000 --- a/src/python/grpcio/grpc/framework/base/_expiration.py +++ /dev/null @@ -1,158 +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. - -"""State and behavior for operation expiration.""" - -import time - -from grpc.framework.base import _interfaces -from grpc.framework.base import interfaces -from grpc.framework.foundation import later - - -class _ExpirationManager(_interfaces.ExpirationManager): - """An implementation of _interfaces.ExpirationManager.""" - - def __init__( - self, lock, termination_manager, transmission_manager, ingestion_manager, - commencement, timeout, maximum_timeout): - """Constructor. - - Args: - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - ingestion_manager: The _interfaces.IngestionManager for the operation. - commencement: The time in seconds since the epoch at which the operation - began. - timeout: A length of time in seconds to allow for the operation to run. - maximum_timeout: The maximum length of time in seconds to allow for the - operation to run despite what is requested via this object's - change_timout method. - """ - self._lock = lock - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._ingestion_manager = ingestion_manager - self._commencement = commencement - self._maximum_timeout = maximum_timeout - - self._timeout = timeout - self._deadline = commencement + timeout - self._index = None - self._future = None - - def _expire(self, index): - with self._lock: - if self._future is not None and index == self._index: - self._future = None - self._termination_manager.abort(interfaces.Outcome.EXPIRED) - self._transmission_manager.abort(interfaces.Outcome.EXPIRED) - self._ingestion_manager.abort() - - def start(self): - self._index = 0 - self._future = later.later(self._timeout, lambda: self._expire(0)) - - def change_timeout(self, timeout): - if self._future is not None and timeout != self._timeout: - self._future.cancel() - new_timeout = min(timeout, self._maximum_timeout) - new_index = self._index + 1 - self._timeout = new_timeout - self._deadline = self._commencement + new_timeout - self._index = new_index - delay = self._deadline - time.time() - self._future = later.later( - delay, lambda: self._expire(new_index)) - - def deadline(self): - return self._deadline - - def abort(self): - if self._future: - self._future.cancel() - self._future = None - self._deadline_index = None - - -def front_expiration_manager( - lock, termination_manager, transmission_manager, ingestion_manager, - timeout): - """Creates an _interfaces.ExpirationManager appropriate for front-side use. - - Args: - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - ingestion_manager: The _interfaces.IngestionManager for the operation. - timeout: A length of time in seconds to allow for the operation to run. - - Returns: - An _interfaces.ExpirationManager appropriate for front-side use. - """ - commencement = time.time() - expiration_manager = _ExpirationManager( - lock, termination_manager, transmission_manager, ingestion_manager, - commencement, timeout, timeout) - expiration_manager.start() - return expiration_manager - - -def back_expiration_manager( - lock, termination_manager, transmission_manager, ingestion_manager, - timeout, default_timeout, maximum_timeout): - """Creates an _interfaces.ExpirationManager appropriate for back-side use. - - Args: - lock: The operation-wide lock. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - ingestion_manager: The _interfaces.IngestionManager for the operation. - timeout: A length of time in seconds to allow for the operation to run. May - be None in which case default_timeout will be used. - default_timeout: The default length of time in seconds to allow for the - operation to run if the front-side customer has not specified such a value - (or if the value they specified is not yet known). - maximum_timeout: The maximum length of time in seconds to allow for the - operation to run. - - Returns: - An _interfaces.ExpirationManager appropriate for back-side use. - """ - commencement = time.time() - expiration_manager = _ExpirationManager( - lock, termination_manager, transmission_manager, ingestion_manager, - commencement, default_timeout if timeout is None else timeout, - maximum_timeout) - expiration_manager.start() - return expiration_manager diff --git a/src/python/grpcio/grpc/framework/base/_ingestion.py b/src/python/grpcio/grpc/framework/base/_ingestion.py deleted file mode 100644 index c9b10acb77..0000000000 --- a/src/python/grpcio/grpc/framework/base/_ingestion.py +++ /dev/null @@ -1,443 +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. - -"""State and behavior for ingestion during an operation.""" - -import abc -import collections - -import six - -from grpc.framework.base import _constants -from grpc.framework.base import _interfaces -from grpc.framework.base import exceptions -from grpc.framework.base import interfaces -from grpc.framework.foundation import abandonment -from grpc.framework.foundation import callable_util -from grpc.framework.foundation import stream - -_CREATE_CONSUMER_EXCEPTION_LOG_MESSAGE = 'Exception initializing ingestion!' -_CONSUME_EXCEPTION_LOG_MESSAGE = 'Exception during ingestion!' - - -class _ConsumerCreation(collections.namedtuple( - '_ConsumerCreation', ('consumer', 'remote_error', 'abandoned'))): - """A sum type for the outcome of ingestion initialization. - - Either consumer will be non-None, remote_error will be True, or abandoned will - be True. - - Attributes: - consumer: A stream.Consumer for ingesting payloads. - remote_error: A boolean indicating that the consumer could not be created - due to an error on the remote side of the operation. - abandoned: A boolean indicating that the consumer creation was abandoned. - """ - - -class _EmptyConsumer(stream.Consumer): - """A no-operative stream.Consumer that ignores all inputs and calls.""" - - def consume(self, value): - """See stream.Consumer.consume for specification.""" - - def terminate(self): - """See stream.Consumer.terminate for specification.""" - - def consume_and_terminate(self, value): - """See stream.Consumer.consume_and_terminate for specification.""" - - -class _ConsumerCreator(six.with_metaclass(abc.ABCMeta)): - """Common specification of different consumer-creating behavior.""" - - @abc.abstractmethod - def create_consumer(self, requirement): - """Creates the stream.Consumer to which customer payloads will be delivered. - - Any exceptions raised by this method should be attributed to and treated as - defects in the serviced or servicer code called by this method. - - Args: - requirement: A value required by this _ConsumerCreator for consumer - creation. - - Returns: - A _ConsumerCreation describing the result of consumer creation. - """ - raise NotImplementedError() - - -class _FrontConsumerCreator(_ConsumerCreator): - """A _ConsumerCreator appropriate for front-side use.""" - - def __init__(self, subscription, operation_context): - """Constructor. - - Args: - subscription: The serviced's interfaces.ServicedSubscription for the - operation. - operation_context: The interfaces.OperationContext object for the - operation. - """ - self._subscription = subscription - self._operation_context = operation_context - - def create_consumer(self, requirement): - """See _ConsumerCreator.create_consumer for specification.""" - if self._subscription.kind is interfaces.ServicedSubscription.Kind.FULL: - try: - return _ConsumerCreation( - self._subscription.ingestor.consumer(self._operation_context), - False, False) - except abandonment.Abandoned: - return _ConsumerCreation(None, False, True) - else: - return _ConsumerCreation(_EmptyConsumer(), False, False) - - -class _BackConsumerCreator(_ConsumerCreator): - """A _ConsumerCreator appropriate for back-side use.""" - - def __init__(self, servicer, operation_context, emission_consumer): - """Constructor. - - Args: - servicer: The interfaces.Servicer that will service the operation. - operation_context: The interfaces.OperationContext object for the - operation. - emission_consumer: The stream.Consumer object to which payloads emitted - from the operation will be passed. - """ - self._servicer = servicer - self._operation_context = operation_context - self._emission_consumer = emission_consumer - - def create_consumer(self, requirement): - """See _ConsumerCreator.create_consumer for full specification. - - Args: - requirement: The name of the Servicer method to be called during this - operation. - - Returns: - A _ConsumerCreation describing the result of consumer creation. - """ - try: - return _ConsumerCreation( - self._servicer.service( - requirement, self._operation_context, self._emission_consumer), - False, False) - except exceptions.NoSuchMethodError: - return _ConsumerCreation(None, True, False) - except abandonment.Abandoned: - return _ConsumerCreation(None, False, True) - - -class _WrappedConsumer(object): - """Wraps a consumer to catch the exceptions that it is allowed to throw.""" - - def __init__(self, consumer): - """Constructor. - - Args: - consumer: A stream.Consumer that may raise abandonment.Abandoned from any - of its methods. - """ - self._consumer = consumer - - def moar(self, payload, complete): - """Makes progress with the wrapped consumer. - - This method catches all exceptions allowed to be thrown by the wrapped - consumer. Any exceptions raised by this method should be blamed on the - customer-supplied consumer. - - Args: - payload: A customer-significant payload object. May be None only if - complete is True. - complete: Whether or not the end of the payload sequence has been reached. - Must be True if payload is None. - - Returns: - True if the wrapped consumer made progress or False if the wrapped - consumer raised abandonment.Abandoned to indicate its abandonment of - progress. - """ - try: - if payload is None: - self._consumer.terminate() - elif complete: - self._consumer.consume_and_terminate(payload) - else: - self._consumer.consume(payload) - return True - except abandonment.Abandoned: - return False - - -class _IngestionManager(_interfaces.IngestionManager): - """An implementation of _interfaces.IngestionManager.""" - - def __init__( - self, lock, pool, consumer_creator, failure_outcome, termination_manager, - transmission_manager): - """Constructor. - - Args: - lock: The operation-wide lock. - pool: A thread pool in which to execute customer code. - consumer_creator: A _ConsumerCreator wrapping the portion of customer code - that when called returns the stream.Consumer with which the customer - code will ingest payload values. - failure_outcome: Whichever one of - interfaces.Outcome.SERVICED_FAILURE or - interfaces.Outcome.SERVICER_FAILURE describes local failure of - customer code. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - """ - self._lock = lock - self._pool = pool - self._consumer_creator = consumer_creator - self._failure_outcome = failure_outcome - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._expiration_manager = None - - self._wrapped_ingestion_consumer = None - self._pending_ingestion = [] - self._ingestion_complete = False - self._processing = False - - def set_expiration_manager(self, expiration_manager): - self._expiration_manager = expiration_manager - - def _abort_internal_only(self): - self._wrapped_ingestion_consumer = None - self._pending_ingestion = None - - def _abort_and_notify(self, outcome): - self._abort_internal_only() - self._termination_manager.abort(outcome) - self._transmission_manager.abort(outcome) - self._expiration_manager.abort() - - def _next(self): - """Computes the next step for ingestion. - - Returns: - A payload, complete, continue triplet indicating what payload (if any) is - available to feed into customer code, whether or not the sequence of - payloads has terminated, and whether or not there is anything - immediately actionable to call customer code to do. - """ - if self._pending_ingestion is None: - return None, False, False - elif self._pending_ingestion: - payload = self._pending_ingestion.pop(0) - complete = self._ingestion_complete and not self._pending_ingestion - return payload, complete, True - elif self._ingestion_complete: - return None, True, True - else: - return None, False, False - - def _process(self, wrapped_ingestion_consumer, payload, complete): - """A method to call to execute customer code. - - This object's lock must *not* be held when calling this method. - - Args: - wrapped_ingestion_consumer: The _WrappedConsumer with which to pass - payloads to customer code. - payload: A customer payload. May be None only if complete is True. - complete: Whether or not the sequence of payloads to pass to the customer - has concluded. - """ - while True: - consumption_outcome = callable_util.call_logging_exceptions( - wrapped_ingestion_consumer.moar, _CONSUME_EXCEPTION_LOG_MESSAGE, - payload, complete) - if consumption_outcome.exception is None: - if consumption_outcome.return_value: - with self._lock: - if complete: - self._pending_ingestion = None - self._termination_manager.ingestion_complete() - return - else: - payload, complete, moar = self._next() - if not moar: - self._processing = False - return - else: - with self._lock: - if self._pending_ingestion is not None: - self._abort_and_notify(self._failure_outcome) - self._processing = False - return - else: - with self._lock: - self._abort_and_notify(self._failure_outcome) - self._processing = False - return - - def start(self, requirement): - if self._pending_ingestion is not None: - def initialize(): - consumer_creation_outcome = callable_util.call_logging_exceptions( - self._consumer_creator.create_consumer, - _CREATE_CONSUMER_EXCEPTION_LOG_MESSAGE, requirement) - if consumer_creation_outcome.return_value is None: - with self._lock: - self._abort_and_notify(self._failure_outcome) - self._processing = False - elif consumer_creation_outcome.return_value.remote_error: - with self._lock: - self._abort_and_notify(interfaces.Outcome.RECEPTION_FAILURE) - self._processing = False - elif consumer_creation_outcome.return_value.abandoned: - with self._lock: - if self._pending_ingestion is not None: - self._abort_and_notify(self._failure_outcome) - self._processing = False - else: - wrapped_ingestion_consumer = _WrappedConsumer( - consumer_creation_outcome.return_value.consumer) - with self._lock: - self._wrapped_ingestion_consumer = wrapped_ingestion_consumer - payload, complete, moar = self._next() - if not moar: - self._processing = False - return - - self._process(wrapped_ingestion_consumer, payload, complete) - - self._pool.submit( - callable_util.with_exceptions_logged( - initialize, _constants.INTERNAL_ERROR_LOG_MESSAGE)) - self._processing = True - - def consume(self, payload): - if self._ingestion_complete: - self._abort_and_notify(self._failure_outcome) - elif self._pending_ingestion is not None: - if self._processing: - self._pending_ingestion.append(payload) - else: - self._pool.submit( - callable_util.with_exceptions_logged( - self._process, _constants.INTERNAL_ERROR_LOG_MESSAGE), - self._wrapped_ingestion_consumer, payload, False) - self._processing = True - - def terminate(self): - if self._ingestion_complete: - self._abort_and_notify(self._failure_outcome) - else: - self._ingestion_complete = True - if self._pending_ingestion is not None and not self._processing: - self._pool.submit( - callable_util.with_exceptions_logged( - self._process, _constants.INTERNAL_ERROR_LOG_MESSAGE), - self._wrapped_ingestion_consumer, None, True) - self._processing = True - - def consume_and_terminate(self, payload): - if self._ingestion_complete: - self._abort_and_notify(self._failure_outcome) - else: - self._ingestion_complete = True - if self._pending_ingestion is not None: - if self._processing: - self._pending_ingestion.append(payload) - else: - self._pool.submit( - callable_util.with_exceptions_logged( - self._process, _constants.INTERNAL_ERROR_LOG_MESSAGE), - self._wrapped_ingestion_consumer, payload, True) - self._processing = True - - def abort(self): - """See _interfaces.IngestionManager.abort for specification.""" - self._abort_internal_only() - - -def front_ingestion_manager( - lock, pool, subscription, termination_manager, transmission_manager, - operation_context): - """Creates an IngestionManager appropriate for front-side use. - - Args: - lock: The operation-wide lock. - pool: A thread pool in which to execute customer code. - subscription: A interfaces.ServicedSubscription indicating the - customer's interest in the results of the operation. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - operation_context: A interfaces.OperationContext for the operation. - - Returns: - An IngestionManager appropriate for front-side use. - """ - ingestion_manager = _IngestionManager( - lock, pool, _FrontConsumerCreator(subscription, operation_context), - interfaces.Outcome.SERVICED_FAILURE, termination_manager, - transmission_manager) - ingestion_manager.start(None) - return ingestion_manager - - -def back_ingestion_manager( - lock, pool, servicer, termination_manager, transmission_manager, - operation_context, emission_consumer): - """Creates an IngestionManager appropriate for back-side use. - - Args: - lock: The operation-wide lock. - pool: A thread pool in which to execute customer code. - servicer: A interfaces.Servicer for servicing the operation. - termination_manager: The _interfaces.TerminationManager for the operation. - transmission_manager: The _interfaces.TransmissionManager for the - operation. - operation_context: A interfaces.OperationContext for the operation. - emission_consumer: The _interfaces.EmissionConsumer for the operation. - - Returns: - An IngestionManager appropriate for back-side use. - """ - ingestion_manager = _IngestionManager( - lock, pool, _BackConsumerCreator( - servicer, operation_context, emission_consumer), - interfaces.Outcome.SERVICER_FAILURE, termination_manager, - transmission_manager) - return ingestion_manager diff --git a/src/python/grpcio/grpc/framework/base/_interfaces.py b/src/python/grpcio/grpc/framework/base/_interfaces.py deleted file mode 100644 index 6bb9837c4a..0000000000 --- a/src/python/grpcio/grpc/framework/base/_interfaces.py +++ /dev/null @@ -1,266 +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. - -"""Package-internal interfaces.""" - -import abc - -import six - -# interfaces is referenced from specification in this module. -from grpc.framework.base import interfaces # pylint: disable=unused-import -from grpc.framework.foundation import stream - - -class TerminationManager(six.with_metaclass(abc.ABCMeta)): - """An object responsible for handling the termination of an operation.""" - - @abc.abstractmethod - def set_expiration_manager(self, expiration_manager): - """Sets the ExpirationManager with which this object will cooperate.""" - raise NotImplementedError() - - @abc.abstractmethod - def is_active(self): - """Reports whether or not the operation is active. - - Returns: - True if the operation is active or False if the operation has terminated. - """ - raise NotImplementedError() - - @abc.abstractmethod - def add_callback(self, callback): - """Registers a callback to be called on operation termination. - - If the operation has already terminated, the callback will be called - immediately. - - Args: - callback: A callable that will be passed an interfaces.Outcome value. - """ - raise NotImplementedError() - - @abc.abstractmethod - def emission_complete(self): - """Indicates that emissions from customer code have completed.""" - raise NotImplementedError() - - @abc.abstractmethod - def transmission_complete(self): - """Indicates that transmissions to the remote end are complete.""" - raise NotImplementedError() - - @abc.abstractmethod - def ingestion_complete(self): - """Indicates that customer code ingestion of received values is complete.""" - raise NotImplementedError() - - @abc.abstractmethod - def abort(self, outcome): - """Indicates that the operation must abort for the indicated reason. - - Args: - outcome: An interfaces.Outcome indicating operation abortion. - """ - raise NotImplementedError() - - -class TransmissionManager(six.with_metaclass(abc.ABCMeta)): - """A manager responsible for transmitting to the other end of an operation.""" - - @abc.abstractmethod - def inmit(self, emission, complete): - """Accepts a value for transmission to the other end of the operation. - - Args: - emission: A value of some significance to the customer to be transmitted - to the other end of the operation. May be None only if complete is True. - complete: A boolean that if True indicates that customer code has emitted - all values it intends to emit. - """ - raise NotImplementedError() - - @abc.abstractmethod - def abort(self, outcome): - """Indicates that the operation has aborted for the indicated reason. - - Args: - outcome: An interfaces.Outcome indicating operation abortion. - """ - raise NotImplementedError() - - -class EmissionManager(six.with_metaclass(abc.ABCMeta, stream.Consumer)): - """A manager of values emitted by customer code.""" - - @abc.abstractmethod - def set_ingestion_manager_and_expiration_manager( - self, ingestion_manager, expiration_manager): - """Sets two other objects with which this EmissionManager will cooperate. - - Args: - ingestion_manager: The IngestionManager for the operation. - expiration_manager: The ExpirationManager for the operation. - """ - raise NotImplementedError() - - @abc.abstractmethod - def consume(self, value): - """Accepts a value emitted by customer code. - - This method should only be called by customer code. - - Args: - value: Any value of significance to the customer. - """ - raise NotImplementedError() - - @abc.abstractmethod - def terminate(self): - """Indicates that no more values will be emitted by customer code. - - This method should only be called by customer code. - - Implementations of this method may be idempotent and forgive customer code - calling this method more than once. - """ - raise NotImplementedError() - - @abc.abstractmethod - def consume_and_terminate(self, value): - """Accepts the last value emitted by customer code. - - This method should only be called by customer code. - - Args: - value: Any value of significance to the customer. - """ - raise NotImplementedError() - - -class IngestionManager(six.with_metaclass(abc.ABCMeta, stream.Consumer)): - """A manager responsible for executing customer code.""" - - @abc.abstractmethod - def set_expiration_manager(self, expiration_manager): - """Sets the ExpirationManager with which this object will cooperate.""" - raise NotImplementedError() - - @abc.abstractmethod - def start(self, requirement): - """Commences execution of customer code. - - Args: - requirement: Some value unavailable at the time of this object's - construction that is required to begin executing customer code. - """ - raise NotImplementedError() - - @abc.abstractmethod - def consume(self, payload): - """Accepts a customer-significant value to be supplied to customer code. - - Args: - payload: Some customer-significant value. - """ - raise NotImplementedError() - - @abc.abstractmethod - def terminate(self): - """Indicates the end of values to be supplied to customer code.""" - raise NotImplementedError() - - @abc.abstractmethod - def consume_and_terminate(self, payload): - """Accepts the last value to be supplied to customer code. - - Args: - payload: Some customer-significant value (and the last such value). - """ - raise NotImplementedError() - - @abc.abstractmethod - def abort(self): - """Indicates to this manager that the operation has aborted.""" - raise NotImplementedError() - - -class ExpirationManager(six.with_metaclass(abc.ABCMeta)): - """A manager responsible for aborting the operation if it runs out of time.""" - - @abc.abstractmethod - def change_timeout(self, timeout): - """Changes the timeout allotted for the operation. - - Operation duration is always measure from the beginning of the operation; - calling this method changes the operation's allotted time to timeout total - seconds, not timeout seconds from the time of this method call. - - Args: - timeout: A length of time in seconds to allow for the operation. - """ - raise NotImplementedError() - - @abc.abstractmethod - def deadline(self): - """Returns the time until which the operation is allowed to run. - - Returns: - The time (seconds since the epoch) at which the operation will expire. - """ - raise NotImplementedError() - - @abc.abstractmethod - def abort(self): - """Indicates to this manager that the operation has aborted.""" - raise NotImplementedError() - - -class ReceptionManager(six.with_metaclass(abc.ABCMeta)): - """A manager responsible for receiving tickets from the other end.""" - - @abc.abstractmethod - def receive_ticket(self, ticket): - """Handle a ticket from the other side of the operation. - - Args: - ticket: An interfaces.BackToFrontTicket or interfaces.FrontToBackTicket - appropriate to this end of the operation and this object. - """ - raise NotImplementedError() - - -class CancellationManager(six.with_metaclass(abc.ABCMeta)): - """A manager of operation cancellation.""" - - @abc.abstractmethod - def cancel(self): - """Cancels the operation.""" - raise NotImplementedError() diff --git a/src/python/grpcio/grpc/framework/base/_reception.py b/src/python/grpcio/grpc/framework/base/_reception.py deleted file mode 100644 index a59c5165f9..0000000000 --- a/src/python/grpcio/grpc/framework/base/_reception.py +++ /dev/null @@ -1,400 +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. - -"""State and behavior for ticket reception.""" - -import abc - -import six - -from grpc.framework.base import interfaces -from grpc.framework.base import _interfaces - -_INITIAL_FRONT_TO_BACK_TICKET_KINDS = ( - interfaces.FrontToBackTicket.Kind.COMMENCEMENT, - interfaces.FrontToBackTicket.Kind.ENTIRE, -) - - -class _Receiver(six.with_metaclass(abc.ABCMeta)): - """Common specification of different ticket-handling behavior.""" - - @abc.abstractmethod - def abort_if_abortive(self, ticket): - """Aborts the operation if the ticket is abortive. - - Args: - ticket: A just-arrived ticket. - - Returns: - A boolean indicating whether or not this Receiver aborted the operation - based on the ticket. - """ - raise NotImplementedError() - - @abc.abstractmethod - def receive(self, ticket): - """Handles a just-arrived ticket. - - Args: - ticket: A just-arrived ticket. - - Returns: - A boolean indicating whether or not the ticket was terminal (i.e. whether - or not non-abortive tickets are legal after this one). - """ - raise NotImplementedError() - - @abc.abstractmethod - def reception_failure(self): - """Aborts the operation with an indication of reception failure.""" - raise NotImplementedError() - - -def _abort( - outcome, termination_manager, transmission_manager, ingestion_manager, - expiration_manager): - """Indicates abortion with the given outcome to the given managers.""" - termination_manager.abort(outcome) - transmission_manager.abort(outcome) - ingestion_manager.abort() - expiration_manager.abort() - - -def _abort_if_abortive( - ticket, abortive, termination_manager, transmission_manager, - ingestion_manager, expiration_manager): - """Determines a ticket's being abortive and if so aborts the operation. - - Args: - ticket: A just-arrived ticket. - abortive: A callable that takes a ticket and returns an interfaces.Outcome - indicating that the operation should be aborted or None indicating that - the operation should not be aborted. - termination_manager: The operation's _interfaces.TerminationManager. - transmission_manager: The operation's _interfaces.TransmissionManager. - ingestion_manager: The operation's _interfaces.IngestionManager. - expiration_manager: The operation's _interfaces.ExpirationManager. - - Returns: - True if the operation was aborted; False otherwise. - """ - abortion_outcome = abortive(ticket) - if abortion_outcome is None: - return False - else: - _abort( - abortion_outcome, termination_manager, transmission_manager, - ingestion_manager, expiration_manager) - return True - - -def _reception_failure( - termination_manager, transmission_manager, ingestion_manager, - expiration_manager): - """Aborts the operation with an indication of reception failure.""" - _abort( - interfaces.Outcome.RECEPTION_FAILURE, termination_manager, - transmission_manager, ingestion_manager, expiration_manager) - - -class _BackReceiver(_Receiver): - """Ticket-handling specific to the back side of an operation.""" - - def __init__( - self, termination_manager, transmission_manager, ingestion_manager, - expiration_manager): - """Constructor. - - Args: - termination_manager: The operation's _interfaces.TerminationManager. - transmission_manager: The operation's _interfaces.TransmissionManager. - ingestion_manager: The operation's _interfaces.IngestionManager. - expiration_manager: The operation's _interfaces.ExpirationManager. - """ - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._ingestion_manager = ingestion_manager - self._expiration_manager = expiration_manager - - self._first_ticket_seen = False - self._last_ticket_seen = False - - def _abortive(self, ticket): - """Determines whether or not (and if so, how) a ticket is abortive. - - Args: - ticket: A just-arrived ticket. - - Returns: - An interfaces.Outcome value describing operation abortion if the - ticket is abortive or None if the ticket is not abortive. - """ - if ticket.kind is interfaces.FrontToBackTicket.Kind.CANCELLATION: - return interfaces.Outcome.CANCELLED - elif ticket.kind is interfaces.FrontToBackTicket.Kind.EXPIRATION: - return interfaces.Outcome.EXPIRED - elif ticket.kind is interfaces.FrontToBackTicket.Kind.SERVICED_FAILURE: - return interfaces.Outcome.SERVICED_FAILURE - elif ticket.kind is interfaces.FrontToBackTicket.Kind.RECEPTION_FAILURE: - return interfaces.Outcome.SERVICED_FAILURE - elif (ticket.kind in _INITIAL_FRONT_TO_BACK_TICKET_KINDS and - self._first_ticket_seen): - return interfaces.Outcome.RECEPTION_FAILURE - elif self._last_ticket_seen: - return interfaces.Outcome.RECEPTION_FAILURE - else: - return None - - def abort_if_abortive(self, ticket): - """See _Receiver.abort_if_abortive for specification.""" - return _abort_if_abortive( - ticket, self._abortive, self._termination_manager, - self._transmission_manager, self._ingestion_manager, - self._expiration_manager) - - def receive(self, ticket): - """See _Receiver.receive for specification.""" - if ticket.timeout is not None: - self._expiration_manager.change_timeout(ticket.timeout) - - if ticket.kind is interfaces.FrontToBackTicket.Kind.COMMENCEMENT: - self._first_ticket_seen = True - self._ingestion_manager.start(ticket.name) - if ticket.payload is not None: - self._ingestion_manager.consume(ticket.payload) - elif ticket.kind is interfaces.FrontToBackTicket.Kind.CONTINUATION: - self._ingestion_manager.consume(ticket.payload) - elif ticket.kind is interfaces.FrontToBackTicket.Kind.COMPLETION: - self._last_ticket_seen = True - if ticket.payload is None: - self._ingestion_manager.terminate() - else: - self._ingestion_manager.consume_and_terminate(ticket.payload) - else: - self._first_ticket_seen = True - self._last_ticket_seen = True - self._ingestion_manager.start(ticket.name) - if ticket.payload is None: - self._ingestion_manager.terminate() - else: - self._ingestion_manager.consume_and_terminate(ticket.payload) - - def reception_failure(self): - """See _Receiver.reception_failure for specification.""" - _reception_failure( - self._termination_manager, self._transmission_manager, - self._ingestion_manager, self._expiration_manager) - - -class _FrontReceiver(_Receiver): - """Ticket-handling specific to the front side of an operation.""" - - def __init__( - self, termination_manager, transmission_manager, ingestion_manager, - expiration_manager): - """Constructor. - - Args: - termination_manager: The operation's _interfaces.TerminationManager. - transmission_manager: The operation's _interfaces.TransmissionManager. - ingestion_manager: The operation's _interfaces.IngestionManager. - expiration_manager: The operation's _interfaces.ExpirationManager. - """ - self._termination_manager = termination_manager - self._transmission_manager = transmission_manager - self._ingestion_manager = ingestion_manager - self._expiration_manager = expiration_manager - - self._last_ticket_seen = False - - def _abortive(self, ticket): - """Determines whether or not (and if so, how) a ticket is abortive. - - Args: - ticket: A just-arrived ticket. - - Returns: - An interfaces.Outcome value describing operation abortion if the ticket - is abortive or None if the ticket is not abortive. - """ - if ticket.kind is interfaces.BackToFrontTicket.Kind.CANCELLATION: - return interfaces.Outcome.CANCELLED - elif ticket.kind is interfaces.BackToFrontTicket.Kind.EXPIRATION: - return interfaces.Outcome.EXPIRED - elif ticket.kind is interfaces.BackToFrontTicket.Kind.SERVICER_FAILURE: - return interfaces.Outcome.SERVICER_FAILURE - elif ticket.kind is interfaces.BackToFrontTicket.Kind.RECEPTION_FAILURE: - return interfaces.Outcome.SERVICER_FAILURE - elif self._last_ticket_seen: - return interfaces.Outcome.RECEPTION_FAILURE - else: - return None - - def abort_if_abortive(self, ticket): - """See _Receiver.abort_if_abortive for specification.""" - return _abort_if_abortive( - ticket, self._abortive, self._termination_manager, - self._transmission_manager, self._ingestion_manager, - self._expiration_manager) - - def receive(self, ticket): - """See _Receiver.receive for specification.""" - if ticket.kind is interfaces.BackToFrontTicket.Kind.CONTINUATION: - self._ingestion_manager.consume(ticket.payload) - elif ticket.kind is interfaces.BackToFrontTicket.Kind.COMPLETION: - self._last_ticket_seen = True - if ticket.payload is None: - self._ingestion_manager.terminate() - else: - self._ingestion_manager.consume_and_terminate(ticket.payload) - - def reception_failure(self): - """See _Receiver.reception_failure for specification.""" - _reception_failure( - self._termination_manager, self._transmission_manager, - self._ingestion_manager, self._expiration_manager) - - -class _ReceptionManager(_interfaces.ReceptionManager): - """A ReceptionManager based around a _Receiver passed to it.""" - - def __init__(self, lock, receiver): - """Constructor. - - Args: - lock: The operation-servicing-wide lock object. - receiver: A _Receiver responsible for handling received tickets. - """ - self._lock = lock - self._receiver = receiver - - self._lowest_unseen_sequence_number = 0 - self._out_of_sequence_tickets = {} - self._completed_sequence_number = None - self._aborted = False - - def _sequence_failure(self, ticket): - """Determines a just-arrived ticket's sequential legitimacy. - - Args: - ticket: A just-arrived ticket. - - Returns: - True if the ticket is sequentially legitimate; False otherwise. - """ - if ticket.sequence_number < self._lowest_unseen_sequence_number: - return True - elif ticket.sequence_number in self._out_of_sequence_tickets: - return True - elif (self._completed_sequence_number is not None and - self._completed_sequence_number <= ticket.sequence_number): - return True - else: - return False - - def _process(self, ticket): - """Process those tickets ready to be processed. - - Args: - ticket: A just-arrived ticket the sequence number of which matches this - _ReceptionManager's _lowest_unseen_sequence_number field. - """ - while True: - completed = self._receiver.receive(ticket) - if completed: - self._out_of_sequence_tickets.clear() - self._completed_sequence_number = ticket.sequence_number - self._lowest_unseen_sequence_number = ticket.sequence_number + 1 - return - else: - next_ticket = self._out_of_sequence_tickets.pop( - ticket.sequence_number + 1, None) - if next_ticket is None: - self._lowest_unseen_sequence_number = ticket.sequence_number + 1 - return - else: - ticket = next_ticket - - def receive_ticket(self, ticket): - """See _interfaces.ReceptionManager.receive_ticket for specification.""" - with self._lock: - if self._aborted: - return - elif self._sequence_failure(ticket): - self._receiver.reception_failure() - self._aborted = True - elif self._receiver.abort_if_abortive(ticket): - self._aborted = True - elif ticket.sequence_number == self._lowest_unseen_sequence_number: - self._process(ticket) - else: - self._out_of_sequence_tickets[ticket.sequence_number] = ticket - - -def front_reception_manager( - lock, termination_manager, transmission_manager, ingestion_manager, - expiration_manager): - """Creates a _interfaces.ReceptionManager for front-side use. - - Args: - lock: The operation-servicing-wide lock object. - termination_manager: The operation's _interfaces.TerminationManager. - transmission_manager: The operation's _interfaces.TransmissionManager. - ingestion_manager: The operation's _interfaces.IngestionManager. - expiration_manager: The operation's _interfaces.ExpirationManager. - - Returns: - A _interfaces.ReceptionManager appropriate for front-side use. - """ - return _ReceptionManager( - lock, _FrontReceiver( - termination_manager, transmission_manager, ingestion_manager, - expiration_manager)) - - -def back_reception_manager( - lock, termination_manager, transmission_manager, ingestion_manager, - expiration_manager): - """Creates a _interfaces.ReceptionManager for back-side use. - - Args: - lock: The operation-servicing-wide lock object. - termination_manager: The operation's _interfaces.TerminationManager. - transmission_manager: The operation's _interfaces.TransmissionManager. - ingestion_manager: The operation's _interfaces.IngestionManager. - expiration_manager: The operation's _interfaces.ExpirationManager. - - Returns: - A _interfaces.ReceptionManager appropriate for back-side use. - """ - return _ReceptionManager( - lock, _BackReceiver( - termination_manager, transmission_manager, ingestion_manager, - expiration_manager)) diff --git a/src/python/grpcio/grpc/framework/base/_termination.py b/src/python/grpcio/grpc/framework/base/_termination.py deleted file mode 100644 index ddcbc60293..0000000000 --- a/src/python/grpcio/grpc/framework/base/_termination.py +++ /dev/null @@ -1,204 +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. - -"""State and behavior for operation termination.""" - -import enum - -from grpc.framework.base import _constants -from grpc.framework.base import _interfaces -from grpc.framework.base import interfaces -from grpc.framework.foundation import callable_util - -_CALLBACK_EXCEPTION_LOG_MESSAGE = 'Exception calling termination callback!' - - -@enum.unique -class _Requirement(enum.Enum): - """Symbols indicating events required for termination.""" - - EMISSION = 'emission' - TRANSMISSION = 'transmission' - INGESTION = 'ingestion' - -_FRONT_NOT_LISTENING_REQUIREMENTS = (_Requirement.TRANSMISSION,) -_BACK_NOT_LISTENING_REQUIREMENTS = ( - _Requirement.EMISSION, _Requirement.INGESTION,) -_LISTENING_REQUIREMENTS = ( - _Requirement.TRANSMISSION, _Requirement.INGESTION,) - - -class _TerminationManager(_interfaces.TerminationManager): - """An implementation of _interfaces.TerminationManager.""" - - def __init__( - self, work_pool, utility_pool, action, requirements, local_failure): - """Constructor. - - Args: - work_pool: A thread pool in which customer work will be done. - utility_pool: A thread pool in which work utility work will be done. - action: An action to call on operation termination. - requirements: A combination of _Requirement values identifying what - must finish for the operation to be considered completed. - local_failure: An interfaces.Outcome specifying what constitutes local - failure of customer work. - """ - self._work_pool = work_pool - self._utility_pool = utility_pool - self._action = action - self._local_failure = local_failure - self._has_locally_failed = False - self._expiration_manager = None - - self._outstanding_requirements = set(requirements) - self._outcome = None - self._callbacks = [] - - def set_expiration_manager(self, expiration_manager): - self._expiration_manager = expiration_manager - - def _terminate(self, outcome): - """Terminates the operation. - - Args: - outcome: An interfaces.Outcome describing the outcome of the operation. - """ - self._expiration_manager.abort() - self._outstanding_requirements = None - callbacks = list(self._callbacks) - self._callbacks = None - self._outcome = outcome - - act = callable_util.with_exceptions_logged( - self._action, _constants.INTERNAL_ERROR_LOG_MESSAGE) - - if self._has_locally_failed: - self._utility_pool.submit(act, outcome) - else: - def call_callbacks_and_act(callbacks, outcome): - for callback in callbacks: - callback_outcome = callable_util.call_logging_exceptions( - callback, _CALLBACK_EXCEPTION_LOG_MESSAGE, outcome) - if callback_outcome.exception is not None: - outcome = self._local_failure - break - self._utility_pool.submit(act, outcome) - - self._work_pool.submit(callable_util.with_exceptions_logged( - call_callbacks_and_act, - _constants.INTERNAL_ERROR_LOG_MESSAGE), - callbacks, outcome) - - def is_active(self): - """See _interfaces.TerminationManager.is_active for specification.""" - return self._outstanding_requirements is not None - - def add_callback(self, callback): - """See _interfaces.TerminationManager.add_callback for specification.""" - if not self._has_locally_failed: - if self._outstanding_requirements is None: - self._work_pool.submit( - callable_util.with_exceptions_logged( - callback, _CALLBACK_EXCEPTION_LOG_MESSAGE), self._outcome) - else: - self._callbacks.append(callback) - - def emission_complete(self): - """See superclass method for specification.""" - if self._outstanding_requirements is not None: - self._outstanding_requirements.discard(_Requirement.EMISSION) - if not self._outstanding_requirements: - self._terminate(interfaces.Outcome.COMPLETED) - - def transmission_complete(self): - """See superclass method for specification.""" - if self._outstanding_requirements is not None: - self._outstanding_requirements.discard(_Requirement.TRANSMISSION) - if not self._outstanding_requirements: - self._terminate(interfaces.Outcome.COMPLETED) - - def ingestion_complete(self): - """See superclass method for specification.""" - if self._outstanding_requirements is not None: - self._outstanding_requirements.discard(_Requirement.INGESTION) - if not self._outstanding_requirements: - self._terminate(interfaces.Outcome.COMPLETED) - - def abort(self, outcome): - """See _interfaces.TerminationManager.abort for specification.""" - if outcome is self._local_failure: - self._has_failed_locally = True - if self._outstanding_requirements is not None: - self._terminate(outcome) - - -def front_termination_manager( - work_pool, utility_pool, action, subscription_kind): - """Creates a TerminationManager appropriate for front-side use. - - Args: - work_pool: A thread pool in which customer work will be done. - utility_pool: A thread pool in which work utility work will be done. - action: An action to call on operation termination. - subscription_kind: An interfaces.ServicedSubscription.Kind value. - - Returns: - A TerminationManager appropriate for front-side use. - """ - if subscription_kind is interfaces.ServicedSubscription.Kind.NONE: - requirements = _FRONT_NOT_LISTENING_REQUIREMENTS - else: - requirements = _LISTENING_REQUIREMENTS - - return _TerminationManager( - work_pool, utility_pool, action, requirements, - interfaces.Outcome.SERVICED_FAILURE) - - -def back_termination_manager(work_pool, utility_pool, action, subscription_kind): - """Creates a TerminationManager appropriate for back-side use. - - Args: - work_pool: A thread pool in which customer work will be done. - utility_pool: A thread pool in which work utility work will be done. - action: An action to call on operation termination. - subscription_kind: An interfaces.ServicedSubscription.Kind value. - - Returns: - A TerminationManager appropriate for back-side use. - """ - if subscription_kind is interfaces.ServicedSubscription.Kind.NONE: - requirements = _BACK_NOT_LISTENING_REQUIREMENTS - else: - requirements = _LISTENING_REQUIREMENTS - - return _TerminationManager( - work_pool, utility_pool, action, requirements, - interfaces.Outcome.SERVICER_FAILURE) diff --git a/src/python/grpcio/grpc/framework/base/_transmission.py b/src/python/grpcio/grpc/framework/base/_transmission.py deleted file mode 100644 index e2a25626f1..0000000000 --- a/src/python/grpcio/grpc/framework/base/_transmission.py +++ /dev/null @@ -1,429 +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. - -"""State and behavior for ticket transmission during an operation.""" - -import abc - -import six - -from grpc.framework.base import _constants -from grpc.framework.base import _interfaces -from grpc.framework.base import interfaces -from grpc.framework.foundation import callable_util - -_TRANSMISSION_EXCEPTION_LOG_MESSAGE = 'Exception during transmission!' - -_FRONT_TO_BACK_NO_TRANSMISSION_OUTCOMES = ( - interfaces.Outcome.SERVICER_FAILURE, - ) -_BACK_TO_FRONT_NO_TRANSMISSION_OUTCOMES = ( - interfaces.Outcome.CANCELLED, - interfaces.Outcome.SERVICED_FAILURE, - ) - -_ABORTION_OUTCOME_TO_FRONT_TO_BACK_TICKET_KIND = { - interfaces.Outcome.CANCELLED: - interfaces.FrontToBackTicket.Kind.CANCELLATION, - interfaces.Outcome.EXPIRED: - interfaces.FrontToBackTicket.Kind.EXPIRATION, - interfaces.Outcome.RECEPTION_FAILURE: - interfaces.FrontToBackTicket.Kind.RECEPTION_FAILURE, - interfaces.Outcome.TRANSMISSION_FAILURE: - interfaces.FrontToBackTicket.Kind.TRANSMISSION_FAILURE, - interfaces.Outcome.SERVICED_FAILURE: - interfaces.FrontToBackTicket.Kind.SERVICED_FAILURE, - interfaces.Outcome.SERVICER_FAILURE: - interfaces.FrontToBackTicket.Kind.SERVICER_FAILURE, -} - -_ABORTION_OUTCOME_TO_BACK_TO_FRONT_TICKET_KIND = { - interfaces.Outcome.CANCELLED: - interfaces.BackToFrontTicket.Kind.CANCELLATION, - interfaces.Outcome.EXPIRED: - interfaces.BackToFrontTicket.Kind.EXPIRATION, - interfaces.Outcome.RECEPTION_FAILURE: - interfaces.BackToFrontTicket.Kind.RECEPTION_FAILURE, - interfaces.Outcome.TRANSMISSION_FAILURE: - interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE, - interfaces.Outcome.SERVICED_FAILURE: - interfaces.BackToFrontTicket.Kind.SERVICED_FAILURE, - interfaces.Outcome.SERVICER_FAILURE: - interfaces.BackToFrontTicket.Kind.SERVICER_FAILURE, -} - - -class _Ticketizer(six.with_metaclass(abc.ABCMeta)): - """Common specification of different ticket-creating behavior.""" - - @abc.abstractmethod - def ticketize(self, operation_id, sequence_number, payload, complete): - """Creates a ticket indicating ordinary operation progress. - - Args: - operation_id: The operation ID for the current operation. - sequence_number: A sequence number for the ticket. - payload: A customer payload object. May be None if sequence_number is - zero or complete is true. - complete: A boolean indicating whether or not the ticket should describe - itself as (but for a later indication of operation abortion) the last - ticket to be sent. - - Returns: - An object of an appropriate type suitable for transmission to the other - side of the operation. - """ - raise NotImplementedError() - - @abc.abstractmethod - def ticketize_abortion(self, operation_id, sequence_number, outcome): - """Creates a ticket indicating that the operation is aborted. - - Args: - operation_id: The operation ID for the current operation. - sequence_number: A sequence number for the ticket. - outcome: An interfaces.Outcome value describing the operation abortion. - - Returns: - An object of an appropriate type suitable for transmission to the other - side of the operation, or None if transmission is not appropriate for - the given outcome. - """ - raise NotImplementedError() - - -class _FrontTicketizer(_Ticketizer): - """Front-side ticket-creating behavior.""" - - def __init__(self, name, subscription_kind, trace_id, timeout): - """Constructor. - - Args: - name: The name of the operation. - subscription_kind: An interfaces.ServicedSubscription.Kind value - describing the interest the front has in tickets sent from the back. - trace_id: A uuid.UUID identifying a set of related operations to which - this operation belongs. - timeout: A length of time in seconds to allow for the entire operation. - """ - self._name = name - self._subscription_kind = subscription_kind - self._trace_id = trace_id - self._timeout = timeout - - def ticketize(self, operation_id, sequence_number, payload, complete): - """See _Ticketizer.ticketize for specification.""" - if sequence_number: - if complete: - kind = interfaces.FrontToBackTicket.Kind.COMPLETION - else: - kind = interfaces.FrontToBackTicket.Kind.CONTINUATION - return interfaces.FrontToBackTicket( - operation_id, sequence_number, kind, self._name, - self._subscription_kind, self._trace_id, payload, self._timeout) - else: - if complete: - kind = interfaces.FrontToBackTicket.Kind.ENTIRE - else: - kind = interfaces.FrontToBackTicket.Kind.COMMENCEMENT - return interfaces.FrontToBackTicket( - operation_id, 0, kind, self._name, self._subscription_kind, - self._trace_id, payload, self._timeout) - - def ticketize_abortion(self, operation_id, sequence_number, outcome): - """See _Ticketizer.ticketize_abortion for specification.""" - if outcome in _FRONT_TO_BACK_NO_TRANSMISSION_OUTCOMES: - return None - else: - kind = _ABORTION_OUTCOME_TO_FRONT_TO_BACK_TICKET_KIND[outcome] - return interfaces.FrontToBackTicket( - operation_id, sequence_number, kind, None, None, None, None, None) - - -class _BackTicketizer(_Ticketizer): - """Back-side ticket-creating behavior.""" - - def ticketize(self, operation_id, sequence_number, payload, complete): - """See _Ticketizer.ticketize for specification.""" - if complete: - kind = interfaces.BackToFrontTicket.Kind.COMPLETION - else: - kind = interfaces.BackToFrontTicket.Kind.CONTINUATION - return interfaces.BackToFrontTicket( - operation_id, sequence_number, kind, payload) - - def ticketize_abortion(self, operation_id, sequence_number, outcome): - """See _Ticketizer.ticketize_abortion for specification.""" - if outcome in _BACK_TO_FRONT_NO_TRANSMISSION_OUTCOMES: - return None - else: - kind = _ABORTION_OUTCOME_TO_BACK_TO_FRONT_TICKET_KIND[outcome] - return interfaces.BackToFrontTicket( - operation_id, sequence_number, kind, None) - - -class TransmissionManager(six.with_metaclass(abc.ABCMeta, _interfaces.TransmissionManager)): - """A _interfaces.TransmissionManager on which other managers may be set.""" - - @abc.abstractmethod - def set_ingestion_and_expiration_managers( - self, ingestion_manager, expiration_manager): - """Sets two of the other managers with which this manager may interact. - - Args: - ingestion_manager: The _interfaces.IngestionManager associated with the - current operation. - expiration_manager: The _interfaces.ExpirationManager associated with the - current operation. - """ - raise NotImplementedError() - - -class _EmptyTransmissionManager(TransmissionManager): - """A completely no-operative _interfaces.TransmissionManager.""" - - def set_ingestion_and_expiration_managers( - self, ingestion_manager, expiration_manager): - """See overriden method for specification.""" - - def inmit(self, emission, complete): - """See _interfaces.TransmissionManager.inmit for specification.""" - - def abort(self, outcome): - """See _interfaces.TransmissionManager.abort for specification.""" - - -class _TransmittingTransmissionManager(TransmissionManager): - """A TransmissionManager implementation that sends tickets.""" - - def __init__( - self, lock, pool, callback, operation_id, ticketizer, - termination_manager): - """Constructor. - - Args: - lock: The operation-servicing-wide lock object. - pool: A thread pool in which the work of transmitting tickets will be - performed. - callback: A callable that accepts tickets and sends them to the other side - of the operation. - operation_id: The operation's ID. - ticketizer: A _Ticketizer for ticket creation. - termination_manager: The _interfaces.TerminationManager associated with - this operation. - """ - self._lock = lock - self._pool = pool - self._callback = callback - self._operation_id = operation_id - self._ticketizer = ticketizer - self._termination_manager = termination_manager - self._ingestion_manager = None - self._expiration_manager = None - - self._emissions = [] - self._emission_complete = False - self._outcome = None - self._lowest_unused_sequence_number = 0 - self._transmitting = False - - def set_ingestion_and_expiration_managers( - self, ingestion_manager, expiration_manager): - """See overridden method for specification.""" - self._ingestion_manager = ingestion_manager - self._expiration_manager = expiration_manager - - def _lead_ticket(self, emission, complete): - """Creates a ticket suitable for leading off the transmission loop. - - Args: - emission: A customer payload object to be sent to the other side of the - operation. - complete: Whether or not the sequence of customer payloads ends with - the passed object. - - Returns: - A ticket with which to lead off the transmission loop. - """ - sequence_number = self._lowest_unused_sequence_number - self._lowest_unused_sequence_number += 1 - return self._ticketizer.ticketize( - self._operation_id, sequence_number, emission, complete) - - def _abortive_response_ticket(self, outcome): - """Creates a ticket indicating operation abortion. - - Args: - outcome: An interfaces.Outcome value describing operation abortion. - - Returns: - A ticket indicating operation abortion. - """ - ticket = self._ticketizer.ticketize_abortion( - self._operation_id, self._lowest_unused_sequence_number, outcome) - if ticket is None: - return None - else: - self._lowest_unused_sequence_number += 1 - return ticket - - def _next_ticket(self): - """Creates the next ticket to be sent to the other side of the operation. - - Returns: - A (completed, ticket) tuple comprised of a boolean indicating whether or - not the sequence of tickets has completed normally and a ticket to send - to the other side if the sequence of tickets hasn't completed. The tuple - will never have both a True first element and a non-None second element. - """ - if self._emissions is None: - return False, None - elif self._outcome is None: - if self._emissions: - payload = self._emissions.pop(0) - complete = self._emission_complete and not self._emissions - sequence_number = self._lowest_unused_sequence_number - self._lowest_unused_sequence_number += 1 - return complete, self._ticketizer.ticketize( - self._operation_id, sequence_number, payload, complete) - else: - return self._emission_complete, None - else: - ticket = self._abortive_response_ticket(self._outcome) - self._emissions = None - return False, None if ticket is None else ticket - - def _transmit(self, ticket): - """Commences the transmission loop sending tickets. - - Args: - ticket: A ticket to be sent to the other side of the operation. - """ - def transmit(ticket): - while True: - transmission_outcome = callable_util.call_logging_exceptions( - self._callback, _TRANSMISSION_EXCEPTION_LOG_MESSAGE, ticket) - if transmission_outcome.exception is None: - with self._lock: - complete, ticket = self._next_ticket() - if ticket is None: - if complete: - self._termination_manager.transmission_complete() - self._transmitting = False - return - else: - with self._lock: - self._emissions = None - self._termination_manager.abort( - interfaces.Outcome.TRANSMISSION_FAILURE) - self._ingestion_manager.abort() - self._expiration_manager.abort() - self._transmitting = False - return - - self._pool.submit(callable_util.with_exceptions_logged( - transmit, _constants.INTERNAL_ERROR_LOG_MESSAGE), ticket) - self._transmitting = True - - def inmit(self, emission, complete): - """See _interfaces.TransmissionManager.inmit for specification.""" - if self._emissions is not None and self._outcome is None: - self._emission_complete = complete - if self._transmitting: - self._emissions.append(emission) - else: - self._transmit(self._lead_ticket(emission, complete)) - - def abort(self, outcome): - """See _interfaces.TransmissionManager.abort for specification.""" - if self._emissions is not None and self._outcome is None: - self._outcome = outcome - if not self._transmitting: - ticket = self._abortive_response_ticket(outcome) - self._emissions = None - if ticket is not None: - self._transmit(ticket) - - -def front_transmission_manager( - lock, pool, callback, operation_id, name, subscription_kind, trace_id, - timeout, termination_manager): - """Creates a TransmissionManager appropriate for front-side use. - - Args: - lock: The operation-servicing-wide lock object. - pool: A thread pool in which the work of transmitting tickets will be - performed. - callback: A callable that accepts tickets and sends them to the other side - of the operation. - operation_id: The operation's ID. - name: The name of the operation. - subscription_kind: An interfaces.ServicedSubscription.Kind value - describing the interest the front has in tickets sent from the back. - trace_id: A uuid.UUID identifying a set of related operations to which - this operation belongs. - timeout: A length of time in seconds to allow for the entire operation. - termination_manager: The _interfaces.TerminationManager associated with - this operation. - - Returns: - A TransmissionManager appropriate for front-side use. - """ - return _TransmittingTransmissionManager( - lock, pool, callback, operation_id, _FrontTicketizer( - name, subscription_kind, trace_id, timeout), - termination_manager) - - -def back_transmission_manager( - lock, pool, callback, operation_id, termination_manager, - subscription_kind): - """Creates a TransmissionManager appropriate for back-side use. - - Args: - lock: The operation-servicing-wide lock object. - pool: A thread pool in which the work of transmitting tickets will be - performed. - callback: A callable that accepts tickets and sends them to the other side - of the operation. - operation_id: The operation's ID. - termination_manager: The _interfaces.TerminationManager associated with - this operation. - subscription_kind: An interfaces.ServicedSubscription.Kind value - describing the interest the front has in tickets sent from the back. - - Returns: - A TransmissionManager appropriate for back-side use. - """ - if subscription_kind is interfaces.ServicedSubscription.Kind.NONE: - return _EmptyTransmissionManager() - else: - return _TransmittingTransmissionManager( - lock, pool, callback, operation_id, _BackTicketizer(), - termination_manager) diff --git a/src/python/grpcio/grpc/framework/base/exceptions.py b/src/python/grpcio/grpc/framework/base/exceptions.py deleted file mode 100644 index b8f4752184..0000000000 --- a/src/python/grpcio/grpc/framework/base/exceptions.py +++ /dev/null @@ -1,34 +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. - -"""Exceptions defined and used by the base layer of RPC Framework.""" - - -class NoSuchMethodError(Exception): - """Indicates that an operation with an unrecognized name has been called.""" diff --git a/src/python/grpcio/grpc/framework/base/implementations.py b/src/python/grpcio/grpc/framework/base/implementations.py deleted file mode 100644 index 5656f9f981..0000000000 --- a/src/python/grpcio/grpc/framework/base/implementations.py +++ /dev/null @@ -1,77 +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. - -"""Entry points into the ticket-exchange-based base layer implementation.""" - -# interfaces is referenced from specification in this module. -from grpc.framework.base import _ends -from grpc.framework.base import interfaces # pylint: disable=unused-import - - -def front_link(work_pool, transmission_pool, utility_pool): - """Factory function for creating interfaces.FrontLinks. - - Args: - work_pool: A thread pool to be used for doing work within the created - FrontLink object. - transmission_pool: A thread pool to be used within the created FrontLink - object for transmitting values to a joined RearLink object. - utility_pool: A thread pool to be used within the created FrontLink object - for utility tasks. - - Returns: - An interfaces.FrontLink. - """ - return _ends.FrontLink(work_pool, transmission_pool, utility_pool) - - -def back_link( - servicer, work_pool, transmission_pool, utility_pool, default_timeout, - maximum_timeout): - """Factory function for creating interfaces.BackLinks. - - Args: - servicer: An interfaces.Servicer for servicing operations. - work_pool: A thread pool to be used for doing work within the created - BackLink object. - transmission_pool: A thread pool to be used within the created BackLink - object for transmitting values to a joined ForeLink object. - utility_pool: A thread pool to be used within the created BackLink object - for utility tasks. - default_timeout: A length of time in seconds to be used as the default - time alloted for a single operation. - maximum_timeout: A length of time in seconds to be used as the maximum - time alloted for a single operation. - - Returns: - An interfaces.BackLink. - """ - return _ends.BackLink( - servicer, work_pool, transmission_pool, utility_pool, default_timeout, - maximum_timeout) diff --git a/src/python/grpcio/grpc/framework/base/in_memory.py b/src/python/grpcio/grpc/framework/base/in_memory.py deleted file mode 100644 index c92d0bc663..0000000000 --- a/src/python/grpcio/grpc/framework/base/in_memory.py +++ /dev/null @@ -1,108 +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. - -"""In-memory implementations of base layer interfaces.""" - -import threading - -from grpc.framework.base import _constants -from grpc.framework.base import interfaces -from grpc.framework.foundation import callable_util - - -class _Serializer(object): - """A utility for serializing values that may arrive concurrently.""" - - def __init__(self, pool): - self._lock = threading.Lock() - self._pool = pool - self._sink = None - self._spinning = False - self._values = [] - - def _spin(self, sink, value): - while True: - sink(value) - with self._lock: - if self._sink is None or not self._values: - self._spinning = False - return - else: - sink, value = self._sink, self._values.pop(0) - - def set_sink(self, sink): - with self._lock: - self._sink = sink - if sink is not None and self._values and not self._spinning: - self._spinning = True - self._pool.submit( - callable_util.with_exceptions_logged( - self._spin, _constants.INTERNAL_ERROR_LOG_MESSAGE), - sink, self._values.pop(0)) - - def add_value(self, value): - with self._lock: - if self._sink and not self._spinning: - self._spinning = True - self._pool.submit( - callable_util.with_exceptions_logged( - self._spin, _constants.INTERNAL_ERROR_LOG_MESSAGE), - self._sink, value) - else: - self._values.append(value) - - -class Link(interfaces.ForeLink, interfaces.RearLink): - """A trivial implementation of interfaces.ForeLink and interfaces.RearLink.""" - - def __init__(self, pool): - """Constructor. - - Args: - pool: A thread pool to be used for serializing ticket exchange in each - direction. - """ - self._front_to_back = _Serializer(pool) - self._back_to_front = _Serializer(pool) - - def join_fore_link(self, fore_link): - """See interfaces.RearLink.join_fore_link for specification.""" - self._back_to_front.set_sink(fore_link.accept_back_to_front_ticket) - - def join_rear_link(self, rear_link): - """See interfaces.ForeLink.join_rear_link for specification.""" - self._front_to_back.set_sink(rear_link.accept_front_to_back_ticket) - - def accept_front_to_back_ticket(self, ticket): - """See interfaces.ForeLink.accept_front_to_back_ticket for specification.""" - self._front_to_back.add_value(ticket) - - def accept_back_to_front_ticket(self, ticket): - """See interfaces.RearLink.accept_back_to_front_ticket for specification.""" - self._back_to_front.add_value(ticket) diff --git a/src/python/grpcio/grpc/framework/base/interfaces.py b/src/python/grpcio/grpc/framework/base/interfaces.py deleted file mode 100644 index 995b51cd5b..0000000000 --- a/src/python/grpcio/grpc/framework/base/interfaces.py +++ /dev/null @@ -1,353 +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. - -"""Interfaces defined and used by the base layer of RPC Framework.""" - -import abc -import collections -import enum - -import six - -# stream is referenced from specification in this module. -from grpc.framework.foundation import stream # pylint: disable=unused-import - - -@enum.unique -class Outcome(enum.Enum): - """Operation outcomes.""" - - COMPLETED = 'completed' - CANCELLED = 'cancelled' - EXPIRED = 'expired' - RECEPTION_FAILURE = 'reception failure' - TRANSMISSION_FAILURE = 'transmission failure' - SERVICER_FAILURE = 'servicer failure' - SERVICED_FAILURE = 'serviced failure' - - -class OperationContext(six.with_metaclass(abc.ABCMeta)): - """Provides operation-related information and action. - - Attributes: - trace_id: A uuid.UUID identifying a particular set of related operations. - """ - - @abc.abstractmethod - def is_active(self): - """Describes whether the operation is active or has terminated.""" - raise NotImplementedError() - - @abc.abstractmethod - def add_termination_callback(self, callback): - """Adds a function to be called upon operation termination. - - Args: - callback: A callable that will be passed an Outcome value. - """ - raise NotImplementedError() - - @abc.abstractmethod - def time_remaining(self): - """Describes the length of allowed time remaining for the operation. - - Returns: - A nonnegative float indicating the length of allowed time in seconds - remaining for the operation to complete before it is considered to have - timed out. - """ - raise NotImplementedError() - - @abc.abstractmethod - def fail(self, exception): - """Indicates that the operation has failed. - - Args: - exception: An exception germane to the operation failure. May be None. - """ - raise NotImplementedError() - - -class Servicer(six.with_metaclass(abc.ABCMeta)): - """Interface for service implementations.""" - - @abc.abstractmethod - def service(self, name, context, output_consumer): - """Services an operation. - - Args: - name: The name of the operation. - context: A ServicerContext object affording contextual information and - actions. - output_consumer: A stream.Consumer that will accept output values of - the operation. - - Returns: - A stream.Consumer that will accept input values for the operation. - - Raises: - exceptions.NoSuchMethodError: If this Servicer affords no method with the - given name. - abandonment.Abandoned: If the operation has been aborted and there no - longer is any reason to service the operation. - """ - raise NotImplementedError() - - -class Operation(six.with_metaclass(abc.ABCMeta)): - """Representation of an in-progress operation. - - Attributes: - consumer: A stream.Consumer into which payloads constituting the operation's - input may be passed. - context: An OperationContext affording information and action about the - operation. - """ - - @abc.abstractmethod - def cancel(self): - """Cancels this operation.""" - raise NotImplementedError() - - -class ServicedIngestor(six.with_metaclass(abc.ABCMeta)): - """Responsible for accepting the result of an operation.""" - - @abc.abstractmethod - def consumer(self, operation_context): - """Affords a consumer to which operation results will be passed. - - Args: - operation_context: An OperationContext object for the current operation. - - Returns: - A stream.Consumer to which the results of the current operation will be - passed. - - Raises: - abandonment.Abandoned: If the operation has been aborted and there no - longer is any reason to service the operation. - """ - raise NotImplementedError() - - -class ServicedSubscription(six.with_metaclass(abc.ABCMeta)): - """A sum type representing a serviced's interest in an operation. - - Attributes: - kind: A Kind value. - ingestor: A ServicedIngestor. Must be present if kind is Kind.FULL. Must - be None if kind is Kind.TERMINATION_ONLY or Kind.NONE. - """ - - @enum.unique - class Kind(enum.Enum): - """Kinds of subscription.""" - - FULL = 'full' - TERMINATION_ONLY = 'termination only' - NONE = 'none' - - -class End(six.with_metaclass(abc.ABCMeta)): - """Common type for entry-point objects on both sides of an operation.""" - - @abc.abstractmethod - def operation_stats(self): - """Reports the number of terminated operations broken down by outcome. - - Returns: - A dictionary from Outcome value to an integer identifying the number - of operations that terminated with that outcome. - """ - raise NotImplementedError() - - @abc.abstractmethod - def add_idle_action(self, action): - """Adds an action to be called when this End has no ongoing operations. - - Args: - action: A callable that accepts no arguments. - """ - raise NotImplementedError() - - -class Front(six.with_metaclass(abc.ABCMeta, End)): - """Clientish objects that afford the invocation of operations.""" - - @abc.abstractmethod - def operate( - self, name, payload, complete, timeout, subscription, trace_id): - """Commences an operation. - - Args: - name: The name of the method invoked for the operation. - payload: An initial payload for the operation. May be None. - complete: A boolean indicating whether or not additional payloads to be - sent to the servicer may be supplied after this call. - timeout: A length of time in seconds to allow for the operation. - subscription: A ServicedSubscription for the operation. - trace_id: A uuid.UUID identifying a set of related operations to which - this operation belongs. - - Returns: - An Operation object affording information and action about the operation - in progress. - """ - raise NotImplementedError() - - -class Back(six.with_metaclass(abc.ABCMeta, End)): - """Serverish objects that perform the work of operations.""" - - -class FrontToBackTicket( - collections.namedtuple( - 'FrontToBackTicket', - ['operation_id', 'sequence_number', 'kind', 'name', 'subscription', - 'trace_id', 'payload', 'timeout'])): - """A sum type for all values sent from a front to a back. - - Attributes: - operation_id: A unique-with-respect-to-equality hashable object identifying - a particular operation. - sequence_number: A zero-indexed integer sequence number identifying the - ticket's place among all the tickets sent from front to back for this - particular operation. Must be zero if kind is Kind.COMMENCEMENT or - Kind.ENTIRE. Must be positive for any other kind. - kind: A Kind value describing the overall kind of ticket. - name: The name of an operation. Must be present if kind is Kind.COMMENCEMENT - or Kind.ENTIRE. Must be None for any other kind. - subscription: An ServicedSubscription.Kind value describing the interest - the front has in tickets sent from the back. Must be present if - kind is Kind.COMMENCEMENT or Kind.ENTIRE. Must be None for any other kind. - trace_id: A uuid.UUID identifying a set of related operations to which this - operation belongs. May be None. - payload: A customer payload object. Must be present if kind is - Kind.CONTINUATION. Must be None if kind is Kind.CANCELLATION. May be None - for any other kind. - timeout: An optional length of time (measured from the beginning of the - operation) to allow for the entire operation. If None, a default value on - the back will be used. If present and excessively large, the back may - limit the operation to a smaller duration of its choice. May be present - for any ticket kind; setting a value on a later ticket allows fronts - to request time extensions (or even time reductions!) on in-progress - operations. - """ - - @enum.unique - class Kind(enum.Enum): - """Identifies the overall kind of a FrontToBackTicket.""" - - COMMENCEMENT = 'commencement' - CONTINUATION = 'continuation' - COMPLETION = 'completion' - ENTIRE = 'entire' - CANCELLATION = 'cancellation' - EXPIRATION = 'expiration' - SERVICER_FAILURE = 'servicer failure' - SERVICED_FAILURE = 'serviced failure' - RECEPTION_FAILURE = 'reception failure' - TRANSMISSION_FAILURE = 'transmission failure' - - -class BackToFrontTicket( - collections.namedtuple( - 'BackToFrontTicket', - ['operation_id', 'sequence_number', 'kind', 'payload'])): - """A sum type for all values sent from a back to a front. - - Attributes: - operation_id: A unique-with-respect-to-equality hashable object identifying - a particular operation. - sequence_number: A zero-indexed integer sequence number identifying the - ticket's place among all the tickets sent from back to front for this - particular operation. - kind: A Kind value describing the overall kind of ticket. - payload: A customer payload object. Must be present if kind is - Kind.CONTINUATION. May be None if kind is Kind.COMPLETION. Must be None - otherwise. - """ - - @enum.unique - class Kind(enum.Enum): - """Identifies the overall kind of a BackToFrontTicket.""" - - CONTINUATION = 'continuation' - COMPLETION = 'completion' - CANCELLATION = 'cancellation' - EXPIRATION = 'expiration' - SERVICER_FAILURE = 'servicer failure' - SERVICED_FAILURE = 'serviced failure' - RECEPTION_FAILURE = 'reception failure' - TRANSMISSION_FAILURE = 'transmission failure' - - -class ForeLink(six.with_metaclass(abc.ABCMeta)): - """Accepts back-to-front tickets and emits front-to-back tickets.""" - - @abc.abstractmethod - def accept_back_to_front_ticket(self, ticket): - """Accept a BackToFrontTicket. - - Args: - ticket: Any BackToFrontTicket. - """ - raise NotImplementedError() - - @abc.abstractmethod - def join_rear_link(self, rear_link): - """Mates this object with a peer with which it will exchange tickets.""" - raise NotImplementedError() - - -class RearLink(six.with_metaclass(abc.ABCMeta)): - """Accepts front-to-back tickets and emits back-to-front tickets.""" - - @abc.abstractmethod - def accept_front_to_back_ticket(self, ticket): - """Accepts a FrontToBackTicket. - - Args: - ticket: Any FrontToBackTicket. - """ - raise NotImplementedError() - - @abc.abstractmethod - def join_fore_link(self, fore_link): - """Mates this object with a peer with which it will exchange tickets.""" - raise NotImplementedError() - - -class FrontLink(six.with_metaclass(abc.ABCMeta, Front, ForeLink)): - """Clientish objects that operate by sending and receiving tickets.""" - - -class BackLink(six.with_metaclass(abc.ABCMeta, Back, RearLink)): - """Serverish objects that operate by sending and receiving tickets.""" diff --git a/src/python/grpcio/grpc/framework/base/null.py b/src/python/grpcio/grpc/framework/base/null.py deleted file mode 100644 index 1e30d4557b..0000000000 --- a/src/python/grpcio/grpc/framework/base/null.py +++ /dev/null @@ -1,56 +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. - -"""Null links that ignore tickets passed to them.""" - -from grpc.framework.base import interfaces - - -class _NullForeLink(interfaces.ForeLink): - """A do-nothing ForeLink.""" - - def accept_back_to_front_ticket(self, ticket): - pass - - def join_rear_link(self, rear_link): - raise NotImplementedError() - - -class _NullRearLink(interfaces.RearLink): - """A do-nothing RearLink.""" - - def accept_front_to_back_ticket(self, ticket): - pass - - def join_fore_link(self, fore_link): - raise NotImplementedError() - - -NULL_FORE_LINK = _NullForeLink() -NULL_REAR_LINK = _NullRearLink() diff --git a/src/python/grpcio/grpc/framework/base/util.py b/src/python/grpcio/grpc/framework/base/util.py deleted file mode 100644 index c832c826cf..0000000000 --- a/src/python/grpcio/grpc/framework/base/util.py +++ /dev/null @@ -1,94 +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. - -"""Utilities helpful for working with the base layer of RPC Framework.""" - -import collections -import threading - -from grpc.framework.base import interfaces - - -class _ServicedSubscription( - collections.namedtuple('_ServicedSubscription', ['kind', 'ingestor']), - interfaces.ServicedSubscription): - """See interfaces.ServicedSubscription for specification.""" - -_NONE_SUBSCRIPTION = _ServicedSubscription( - interfaces.ServicedSubscription.Kind.NONE, None) -_TERMINATION_ONLY_SUBSCRIPTION = _ServicedSubscription( - interfaces.ServicedSubscription.Kind.TERMINATION_ONLY, None) - - -def none_serviced_subscription(): - """Creates a "none" interfaces.ServicedSubscription object. - - Returns: - An interfaces.ServicedSubscription indicating no subscription to an - operation's results (such as would be the case for a fire-and-forget - operation invocation). - """ - return _NONE_SUBSCRIPTION - - -def termination_only_serviced_subscription(): - """Creates a "termination only" interfaces.ServicedSubscription object. - - Returns: - An interfaces.ServicedSubscription indicating that the front-side customer - is interested only in the overall termination outcome of the operation - (such as completion or expiration) and would ignore the actual results of - the operation. - """ - return _TERMINATION_ONLY_SUBSCRIPTION - - -def full_serviced_subscription(ingestor): - """Creates a "full" interfaces.ServicedSubscription object. - - Args: - ingestor: An interfaces.ServicedIngestor. - - Returns: - An interfaces.ServicedSubscription object indicating a full - subscription. - """ - return _ServicedSubscription( - interfaces.ServicedSubscription.Kind.FULL, ingestor) - - -def wait_for_idle(end): - """Waits for an interfaces.End to complete all operations. - - Args: - end: Any interfaces.End. - """ - event = threading.Event() - end.add_idle_action(event.set) - event.wait() diff --git a/src/python/grpcio/grpc/framework/face/__init__.py b/src/python/grpcio/grpc/framework/face/__init__.py deleted file mode 100644 index bff74be2c7..0000000000 --- a/src/python/grpcio/grpc/framework/face/__init__.py +++ /dev/null @@ -1,35 +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. - -import warnings - -warnings.simplefilter('always', DeprecationWarning) -warnings.warn('the alpha API (includes this package) is deprecated, ' - 'unmaintained, and no longer tested. Please migrate to the beta ' - 'API.', DeprecationWarning, stacklevel=2) diff --git a/src/python/grpcio/grpc/framework/face/_calls.py b/src/python/grpcio/grpc/framework/face/_calls.py deleted file mode 100644 index 87edeb0f0e..0000000000 --- a/src/python/grpcio/grpc/framework/face/_calls.py +++ /dev/null @@ -1,422 +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. - -"""Utility functions for invoking RPCs.""" - -import sys -import threading - -from grpc.framework.base import interfaces as base_interfaces -from grpc.framework.base import util as base_util -from grpc.framework.face import _control -from grpc.framework.face import interfaces -from grpc.framework.foundation import callable_util -from grpc.framework.foundation import future - -_ITERATOR_EXCEPTION_LOG_MESSAGE = 'Exception iterating over requests!' -_DONE_CALLBACK_LOG_MESSAGE = 'Exception calling Future "done" callback!' - - -class _RendezvousServicedIngestor(base_interfaces.ServicedIngestor): - - def __init__(self, rendezvous): - self._rendezvous = rendezvous - - def consumer(self, operation_context): - return self._rendezvous - - -class _EventServicedIngestor(base_interfaces.ServicedIngestor): - - def __init__(self, result_consumer, abortion_callback): - self._result_consumer = result_consumer - self._abortion_callback = abortion_callback - - def consumer(self, operation_context): - operation_context.add_termination_callback( - _control.as_operation_termination_callback(self._abortion_callback)) - return self._result_consumer - - -def _rendezvous_subscription(rendezvous): - return base_util.full_serviced_subscription( - _RendezvousServicedIngestor(rendezvous)) - - -def _unary_event_subscription(completion_callback, abortion_callback): - return base_util.full_serviced_subscription( - _EventServicedIngestor( - _control.UnaryConsumer(completion_callback), abortion_callback)) - - -def _stream_event_subscription(result_consumer, abortion_callback): - return base_util.full_serviced_subscription( - _EventServicedIngestor(result_consumer, abortion_callback)) - - -# NOTE(nathaniel): This class has some extremely special semantics around -# cancellation that allow it to be used by both "blocking" APIs and "futures" -# APIs. -# -# Since futures.Future defines its own exception for cancellation, we want these -# objects, when returned by methods of a returning-Futures-from-other-methods -# object, to raise the same exception for cancellation. But that's weird in a -# blocking API - why should this object, also returned by methods of blocking -# APIs, raise exceptions from the "future" module? Should we do something like -# have this class be parameterized by the type of exception that it raises in -# cancellation circumstances? -# -# We don't have to take such a dramatic step: since blocking APIs define no -# cancellation semantics whatsoever, there is no supported way for -# blocking-API-users of these objects to cancel RPCs, and thus no supported way -# for them to see an exception the type of which would be weird to them. -# -# Bonus: in both blocking and futures APIs, this object still properly raises -# exceptions.CancellationError for any *server-side cancellation* of an RPC. -class _OperationCancellableIterator(interfaces.CancellableIterator): - """An interfaces.CancellableIterator for response-streaming operations.""" - - def __init__(self, rendezvous, operation): - self._lock = threading.Lock() - self._rendezvous = rendezvous - self._operation = operation - self._cancelled = False - - def __iter__(self): - return self - - def next(self): - with self._lock: - if self._cancelled: - raise future.CancelledError() - return next(self._rendezvous) - - def cancel(self): - with self._lock: - self._cancelled = True - self._operation.cancel() - self._rendezvous.set_outcome(base_interfaces.Outcome.CANCELLED) - - -class _OperationFuture(future.Future): - """A future.Future interface to an operation.""" - - def __init__(self, rendezvous, operation): - self._condition = threading.Condition() - self._rendezvous = rendezvous - self._operation = operation - - self._cancelled = False - self._computed = False - self._payload = None - self._exception = None - self._traceback = None - self._callbacks = [] - - def cancel(self): - """See future.Future.cancel for specification.""" - with self._condition: - if not self._cancelled and not self._computed: - self._operation.cancel() - self._cancelled = True - self._condition.notify_all() - return False - - def cancelled(self): - """See future.Future.cancelled for specification.""" - with self._condition: - return self._cancelled - - def running(self): - """See future.Future.running for specification.""" - with self._condition: - return not self._cancelled and not self._computed - - def done(self): - """See future.Future.done for specification.""" - with self._condition: - return self._cancelled or self._computed - - def result(self, timeout=None): - """See future.Future.result for specification.""" - with self._condition: - if self._cancelled: - raise future.CancelledError() - if self._computed: - if self._payload is None: - raise self._exception # pylint: disable=raising-bad-type - else: - return self._payload - - condition = threading.Condition() - def notify_condition(unused_future): - with condition: - condition.notify() - self._callbacks.append(notify_condition) - - with condition: - condition.wait(timeout=timeout) - - with self._condition: - if self._cancelled: - raise future.CancelledError() - elif self._computed: - if self._payload is None: - raise self._exception # pylint: disable=raising-bad-type - else: - return self._payload - else: - raise future.TimeoutError() - - def exception(self, timeout=None): - """See future.Future.exception for specification.""" - with self._condition: - if self._cancelled: - raise future.CancelledError() - if self._computed: - return self._exception - - condition = threading.Condition() - def notify_condition(unused_future): - with condition: - condition.notify() - self._callbacks.append(notify_condition) - - with condition: - condition.wait(timeout=timeout) - - with self._condition: - if self._cancelled: - raise future.CancelledError() - elif self._computed: - return self._exception - else: - raise future.TimeoutError() - - def traceback(self, timeout=None): - """See future.Future.traceback for specification.""" - with self._condition: - if self._cancelled: - raise future.CancelledError() - if self._computed: - return self._traceback - - condition = threading.Condition() - def notify_condition(unused_future): - with condition: - condition.notify() - self._callbacks.append(notify_condition) - - with condition: - condition.wait(timeout=timeout) - - with self._condition: - if self._cancelled: - raise future.CancelledError() - elif self._computed: - return self._traceback - else: - raise future.TimeoutError() - - def add_done_callback(self, fn): - """See future.Future.add_done_callback for specification.""" - with self._condition: - if self._callbacks is not None: - self._callbacks.append(fn) - return - - callable_util.call_logging_exceptions(fn, _DONE_CALLBACK_LOG_MESSAGE, self) - - def on_operation_termination(self, operation_outcome): - """Indicates to this object that the operation has terminated. - - Args: - operation_outcome: A base_interfaces.Outcome value indicating the - outcome of the operation. - """ - with self._condition: - cancelled = self._cancelled - if cancelled: - callbacks = list(self._callbacks) - self._callbacks = None - else: - rendezvous = self._rendezvous - - if not cancelled: - payload = None - exception = None - traceback = None - if operation_outcome == base_interfaces.Outcome.COMPLETED: - try: - payload = next(rendezvous) - except Exception as e: # pylint: disable=broad-except - exception = e - traceback = sys.exc_info()[2] - else: - try: - # We raise and then immediately catch in order to create a traceback. - raise _control.abortion_outcome_to_exception(operation_outcome) - except Exception as e: # pylint: disable=broad-except - exception = e - traceback = sys.exc_info()[2] - with self._condition: - if not self._cancelled: - self._computed = True - self._payload = payload - self._exception = exception - self._traceback = traceback - callbacks = list(self._callbacks) - self._callbacks = None - - for callback in callbacks: - callable_util.call_logging_exceptions( - callback, _DONE_CALLBACK_LOG_MESSAGE, self) - - -class _Call(interfaces.Call): - - def __init__(self, operation): - self._operation = operation - self.context = _control.RpcContext(operation.context) - - def cancel(self): - self._operation.cancel() - - -def blocking_value_in_value_out(front, name, payload, timeout, trace_id): - """Services in a blocking fashion a value-in value-out servicer method.""" - rendezvous = _control.Rendezvous() - subscription = _rendezvous_subscription(rendezvous) - operation = front.operate( - name, payload, True, timeout, subscription, trace_id) - operation.context.add_termination_callback(rendezvous.set_outcome) - return next(rendezvous) - - -def future_value_in_value_out(front, name, payload, timeout, trace_id): - """Services a value-in value-out servicer method by returning a Future.""" - rendezvous = _control.Rendezvous() - subscription = _rendezvous_subscription(rendezvous) - operation = front.operate( - name, payload, True, timeout, subscription, trace_id) - operation.context.add_termination_callback(rendezvous.set_outcome) - operation_future = _OperationFuture(rendezvous, operation) - operation.context.add_termination_callback( - operation_future.on_operation_termination) - return operation_future - - -def inline_value_in_stream_out(front, name, payload, timeout, trace_id): - """Services a value-in stream-out servicer method.""" - rendezvous = _control.Rendezvous() - subscription = _rendezvous_subscription(rendezvous) - operation = front.operate( - name, payload, True, timeout, subscription, trace_id) - operation.context.add_termination_callback(rendezvous.set_outcome) - return _OperationCancellableIterator(rendezvous, operation) - - -def blocking_stream_in_value_out( - front, name, payload_iterator, timeout, trace_id): - """Services in a blocking fashion a stream-in value-out servicer method.""" - rendezvous = _control.Rendezvous() - subscription = _rendezvous_subscription(rendezvous) - operation = front.operate(name, None, False, timeout, subscription, trace_id) - operation.context.add_termination_callback(rendezvous.set_outcome) - for payload in payload_iterator: - operation.consumer.consume(payload) - operation.consumer.terminate() - return next(rendezvous) - - -def future_stream_in_value_out( - front, name, payload_iterator, timeout, trace_id, pool): - """Services a stream-in value-out servicer method by returning a Future.""" - rendezvous = _control.Rendezvous() - subscription = _rendezvous_subscription(rendezvous) - operation = front.operate(name, None, False, timeout, subscription, trace_id) - operation.context.add_termination_callback(rendezvous.set_outcome) - pool.submit( - callable_util.with_exceptions_logged( - _control.pipe_iterator_to_consumer, _ITERATOR_EXCEPTION_LOG_MESSAGE), - payload_iterator, operation.consumer, lambda: True, True) - operation_future = _OperationFuture(rendezvous, operation) - operation.context.add_termination_callback( - operation_future.on_operation_termination) - return operation_future - - -def inline_stream_in_stream_out( - front, name, payload_iterator, timeout, trace_id, pool): - """Services a stream-in stream-out servicer method.""" - rendezvous = _control.Rendezvous() - subscription = _rendezvous_subscription(rendezvous) - operation = front.operate(name, None, False, timeout, subscription, trace_id) - operation.context.add_termination_callback(rendezvous.set_outcome) - pool.submit( - callable_util.with_exceptions_logged( - _control.pipe_iterator_to_consumer, _ITERATOR_EXCEPTION_LOG_MESSAGE), - payload_iterator, operation.consumer, lambda: True, True) - return _OperationCancellableIterator(rendezvous, operation) - - -def event_value_in_value_out( - front, name, payload, completion_callback, abortion_callback, timeout, - trace_id): - subscription = _unary_event_subscription( - completion_callback, abortion_callback) - operation = front.operate( - name, payload, True, timeout, subscription, trace_id) - return _Call(operation) - - -def event_value_in_stream_out( - front, name, payload, result_payload_consumer, abortion_callback, timeout, - trace_id): - subscription = _stream_event_subscription( - result_payload_consumer, abortion_callback) - operation = front.operate( - name, payload, True, timeout, subscription, trace_id) - return _Call(operation) - - -def event_stream_in_value_out( - front, name, completion_callback, abortion_callback, timeout, trace_id): - subscription = _unary_event_subscription( - completion_callback, abortion_callback) - operation = front.operate(name, None, False, timeout, subscription, trace_id) - return _Call(operation), operation.consumer - - -def event_stream_in_stream_out( - front, name, result_payload_consumer, abortion_callback, timeout, trace_id): - subscription = _stream_event_subscription( - result_payload_consumer, abortion_callback) - operation = front.operate(name, None, False, timeout, subscription, trace_id) - return _Call(operation), operation.consumer diff --git a/src/python/grpcio/grpc/framework/face/_control.py b/src/python/grpcio/grpc/framework/face/_control.py deleted file mode 100644 index 539615efa1..0000000000 --- a/src/python/grpcio/grpc/framework/face/_control.py +++ /dev/null @@ -1,201 +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. - -"""State and behavior for translating between sync and async control flow.""" - -import threading - -from grpc.framework.base import interfaces as base_interfaces -from grpc.framework.face import exceptions -from grpc.framework.face import interfaces -from grpc.framework.foundation import abandonment -from grpc.framework.foundation import stream - -INTERNAL_ERROR_LOG_MESSAGE = ':-( RPC Framework (Face) Internal Error! :-(' - -_OPERATION_OUTCOME_TO_RPC_ABORTION = { - base_interfaces.Outcome.CANCELLED: interfaces.Abortion.CANCELLED, - base_interfaces.Outcome.EXPIRED: interfaces.Abortion.EXPIRED, - base_interfaces.Outcome.RECEPTION_FAILURE: - interfaces.Abortion.NETWORK_FAILURE, - base_interfaces.Outcome.TRANSMISSION_FAILURE: - interfaces.Abortion.NETWORK_FAILURE, - base_interfaces.Outcome.SERVICED_FAILURE: - interfaces.Abortion.SERVICED_FAILURE, - base_interfaces.Outcome.SERVICER_FAILURE: - interfaces.Abortion.SERVICER_FAILURE, -} - - -def _as_operation_termination_callback(rpc_abortion_callback): - def operation_termination_callback(operation_outcome): - rpc_abortion = _OPERATION_OUTCOME_TO_RPC_ABORTION.get( - operation_outcome, None) - if rpc_abortion is not None: - rpc_abortion_callback(rpc_abortion) - return operation_termination_callback - - -def _abortion_outcome_to_exception(abortion_outcome): - if abortion_outcome == base_interfaces.Outcome.CANCELLED: - return exceptions.CancellationError() - elif abortion_outcome == base_interfaces.Outcome.EXPIRED: - return exceptions.ExpirationError() - elif abortion_outcome == base_interfaces.Outcome.SERVICER_FAILURE: - return exceptions.ServicerError() - elif abortion_outcome == base_interfaces.Outcome.SERVICED_FAILURE: - return exceptions.ServicedError() - else: - return exceptions.NetworkError() - - -class UnaryConsumer(stream.Consumer): - """A stream.Consumer that should only ever be passed one value.""" - - def __init__(self, on_termination): - self._on_termination = on_termination - self._value = None - - def consume(self, value): - self._value = value - - def terminate(self): - self._on_termination(self._value) - - def consume_and_terminate(self, value): - self._on_termination(value) - - -class Rendezvous(stream.Consumer): - """A rendez-vous with stream.Consumer and iterator interfaces.""" - - def __init__(self): - self._condition = threading.Condition() - self._values = [] - self._values_completed = False - self._abortion = None - - def consume(self, value): - with self._condition: - self._values.append(value) - self._condition.notify() - - def terminate(self): - with self._condition: - self._values_completed = True - self._condition.notify() - - def consume_and_terminate(self, value): - with self._condition: - self._values.append(value) - self._values_completed = True - self._condition.notify() - - def __iter__(self): - return self - - def __next__(self): - return self.next() - - def next(self): - with self._condition: - while ((self._abortion is None) and - (not self._values) and - (not self._values_completed)): - self._condition.wait() - if self._abortion is not None: - raise _abortion_outcome_to_exception(self._abortion) - elif self._values: - return self._values.pop(0) - elif self._values_completed: - raise StopIteration() - else: - raise AssertionError('Unreachable code reached!') - - def set_outcome(self, outcome): - with self._condition: - if outcome is not base_interfaces.Outcome.COMPLETED: - self._abortion = outcome - self._condition.notify() - - -class RpcContext(interfaces.RpcContext): - """A wrapped base_interfaces.OperationContext.""" - - def __init__(self, operation_context): - self._operation_context = operation_context - - def is_active(self): - return self._operation_context.is_active() - - def time_remaining(self): - return self._operation_context.time_remaining() - - def add_abortion_callback(self, abortion_callback): - self._operation_context.add_termination_callback( - _as_operation_termination_callback(abortion_callback)) - - -def pipe_iterator_to_consumer(iterator, consumer, active, terminate): - """Pipes values emitted from an iterator to a stream.Consumer. - - Args: - iterator: An iterator from which values will be emitted. - consumer: A stream.Consumer to which values will be passed. - active: A no-argument callable that returns True if the work being done by - this function is still valid and should not be abandoned and False if the - work being done by this function should be abandoned. - terminate: A boolean indicating whether or not this function should - terminate the given consumer after passing to it all values emitted by the - given iterator. - - Raises: - abandonment.Abandoned: If this function quits early after seeing False - returned by the active function passed to it. - Exception: This function raises whatever exceptions are raised by iterating - over the given iterator. - """ - for element in iterator: - if not active(): - raise abandonment.Abandoned() - - consumer.consume(element) - - if not active(): - raise abandonment.Abandoned() - if terminate: - consumer.terminate() - - -def abortion_outcome_to_exception(abortion_outcome): - return _abortion_outcome_to_exception(abortion_outcome) - - -def as_operation_termination_callback(rpc_abortion_callback): - return _as_operation_termination_callback(rpc_abortion_callback) diff --git a/src/python/grpcio/grpc/framework/face/_service.py b/src/python/grpcio/grpc/framework/face/_service.py deleted file mode 100644 index cdf413356a..0000000000 --- a/src/python/grpcio/grpc/framework/face/_service.py +++ /dev/null @@ -1,187 +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. - -"""Behaviors for servicing RPCs.""" - -# base_interfaces and interfaces are referenced from specification in this -# module. -from grpc.framework.base import interfaces as base_interfaces # pylint: disable=unused-import -from grpc.framework.face import _control -from grpc.framework.face import exceptions -from grpc.framework.face import interfaces # pylint: disable=unused-import -from grpc.framework.foundation import abandonment -from grpc.framework.foundation import callable_util -from grpc.framework.foundation import stream -from grpc.framework.foundation import stream_util - - -class _ValueInStreamOutConsumer(stream.Consumer): - """A stream.Consumer that maps inputs one-to-many onto outputs.""" - - def __init__(self, behavior, context, downstream): - """Constructor. - - Args: - behavior: A callable that takes a single value and an - interfaces.RpcContext and returns a generator of arbitrarily many - values. - context: An interfaces.RpcContext. - downstream: A stream.Consumer to which to pass the values generated by the - given behavior. - """ - self._behavior = behavior - self._context = context - self._downstream = downstream - - def consume(self, value): - _control.pipe_iterator_to_consumer( - self._behavior(value, self._context), self._downstream, - self._context.is_active, False) - - def terminate(self): - self._downstream.terminate() - - def consume_and_terminate(self, value): - _control.pipe_iterator_to_consumer( - self._behavior(value, self._context), self._downstream, - self._context.is_active, True) - - -def _pool_wrap(behavior, operation_context): - """Wraps an operation-related behavior so that it may be called in a pool. - - Args: - behavior: A callable related to carrying out an operation. - operation_context: A base_interfaces.OperationContext for the operation. - - Returns: - A callable that when called carries out the behavior of the given callable - and handles whatever exceptions it raises appropriately. - """ - def translation(*args): - try: - behavior(*args) - except ( - abandonment.Abandoned, - exceptions.ExpirationError, - exceptions.CancellationError, - exceptions.ServicedError, - exceptions.NetworkError) as e: - if operation_context.is_active(): - operation_context.fail(e) - except Exception as e: - operation_context.fail(e) - return callable_util.with_exceptions_logged( - translation, _control.INTERNAL_ERROR_LOG_MESSAGE) - - -def adapt_inline_value_in_value_out(method): - def adaptation(response_consumer, operation_context): - rpc_context = _control.RpcContext(operation_context) - return stream_util.TransformingConsumer( - lambda request: method(request, rpc_context), response_consumer) - return adaptation - - -def adapt_inline_value_in_stream_out(method): - def adaptation(response_consumer, operation_context): - rpc_context = _control.RpcContext(operation_context) - return _ValueInStreamOutConsumer(method, rpc_context, response_consumer) - return adaptation - - -def adapt_inline_stream_in_value_out(method, pool): - def adaptation(response_consumer, operation_context): - rendezvous = _control.Rendezvous() - operation_context.add_termination_callback(rendezvous.set_outcome) - def in_pool_thread(): - response_consumer.consume_and_terminate( - method(rendezvous, _control.RpcContext(operation_context))) - pool.submit(_pool_wrap(in_pool_thread, operation_context)) - return rendezvous - return adaptation - - -def adapt_inline_stream_in_stream_out(method, pool): - """Adapts an interfaces.InlineStreamInStreamOutMethod for use with Consumers. - - RPCs may be serviced by calling the return value of this function, passing - request values to the stream.Consumer returned from that call, and receiving - response values from the stream.Consumer passed to that call. - - Args: - method: An interfaces.InlineStreamInStreamOutMethod. - pool: A thread pool. - - Returns: - A callable that takes a stream.Consumer and a - base_interfaces.OperationContext and returns a stream.Consumer. - """ - def adaptation(response_consumer, operation_context): - rendezvous = _control.Rendezvous() - operation_context.add_termination_callback(rendezvous.set_outcome) - def in_pool_thread(): - _control.pipe_iterator_to_consumer( - method(rendezvous, _control.RpcContext(operation_context)), - response_consumer, operation_context.is_active, True) - pool.submit(_pool_wrap(in_pool_thread, operation_context)) - return rendezvous - return adaptation - - -def adapt_event_value_in_value_out(method): - def adaptation(response_consumer, operation_context): - def on_payload(payload): - method( - payload, response_consumer.consume_and_terminate, - _control.RpcContext(operation_context)) - return _control.UnaryConsumer(on_payload) - return adaptation - - -def adapt_event_value_in_stream_out(method): - def adaptation(response_consumer, operation_context): - def on_payload(payload): - method( - payload, response_consumer, _control.RpcContext(operation_context)) - return _control.UnaryConsumer(on_payload) - return adaptation - - -def adapt_event_stream_in_value_out(method): - def adaptation(response_consumer, operation_context): - rpc_context = _control.RpcContext(operation_context) - return method(response_consumer.consume_and_terminate, rpc_context) - return adaptation - - -def adapt_event_stream_in_stream_out(method): - def adaptation(response_consumer, operation_context): - return method(response_consumer, _control.RpcContext(operation_context)) - return adaptation diff --git a/src/python/grpcio/grpc/framework/face/demonstration.py b/src/python/grpcio/grpc/framework/face/demonstration.py deleted file mode 100644 index f6b4b609ff..0000000000 --- a/src/python/grpcio/grpc/framework/face/demonstration.py +++ /dev/null @@ -1,118 +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. - -"""Demonstration-suitable implementation of the face layer of RPC Framework.""" - -from grpc.framework.base import util as _base_util -from grpc.framework.base import implementations as _base_implementations -from grpc.framework.face import implementations -from grpc.framework.foundation import logging_pool - -_POOL_SIZE_LIMIT = 5 - -_MAXIMUM_TIMEOUT = 90 - - -class LinkedPair(object): - """A Server and Stub that are linked to one another. - - Attributes: - server: A Server. - stub: A Stub. - """ - - def shut_down(self): - """Shuts down this object and releases its resources.""" - raise NotImplementedError() - - -class _LinkedPair(LinkedPair): - - def __init__(self, server, stub, front, back, pools): - self.server = server - self.stub = stub - self._front = front - self._back = back - self._pools = pools - - def shut_down(self): - _base_util.wait_for_idle(self._front) - _base_util.wait_for_idle(self._back) - - for pool in self._pools: - pool.shutdown(wait=True) - - -def server_and_stub( - default_timeout, - inline_value_in_value_out_methods=None, - inline_value_in_stream_out_methods=None, - inline_stream_in_value_out_methods=None, - inline_stream_in_stream_out_methods=None, - event_value_in_value_out_methods=None, - event_value_in_stream_out_methods=None, - event_stream_in_value_out_methods=None, - event_stream_in_stream_out_methods=None, - multi_method=None): - """Creates a Server and Stub linked together for use.""" - front_work_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - front_transmission_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - front_utility_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - back_work_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - back_transmission_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - back_utility_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - stub_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - pools = ( - front_work_pool, front_transmission_pool, front_utility_pool, - back_work_pool, back_transmission_pool, back_utility_pool, - stub_pool) - - servicer = implementations.servicer( - back_work_pool, - inline_value_in_value_out_methods=inline_value_in_value_out_methods, - inline_value_in_stream_out_methods=inline_value_in_stream_out_methods, - inline_stream_in_value_out_methods=inline_stream_in_value_out_methods, - inline_stream_in_stream_out_methods=inline_stream_in_stream_out_methods, - event_value_in_value_out_methods=event_value_in_value_out_methods, - event_value_in_stream_out_methods=event_value_in_stream_out_methods, - event_stream_in_value_out_methods=event_stream_in_value_out_methods, - event_stream_in_stream_out_methods=event_stream_in_stream_out_methods, - multi_method=multi_method) - - front = _base_implementations.front_link( - front_work_pool, front_transmission_pool, front_utility_pool) - back = _base_implementations.back_link( - servicer, back_work_pool, back_transmission_pool, back_utility_pool, - default_timeout, _MAXIMUM_TIMEOUT) - front.join_rear_link(back) - back.join_fore_link(front) - - stub = implementations.stub(front, stub_pool) - - return _LinkedPair(implementations.server(), stub, front, back, pools) diff --git a/src/python/grpcio/grpc/framework/face/exceptions.py b/src/python/grpcio/grpc/framework/face/exceptions.py deleted file mode 100644 index f95455604d..0000000000 --- a/src/python/grpcio/grpc/framework/face/exceptions.py +++ /dev/null @@ -1,78 +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. - -"""Exceptions used in the Face layer of RPC Framework.""" - -import abc - -import six - - -class NoSuchMethodError(Exception): - """Raised by customer code to indicate an unrecognized RPC method name. - - Attributes: - name: The unrecognized name. - """ - - def __init__(self, name): - """Constructor. - - Args: - name: The unrecognized RPC method name. - """ - super(NoSuchMethodError, self).__init__() - self.name = name - - -class RpcError(six.with_metaclass(abc.ABCMeta, Exception)): - """Common super type for all exceptions raised by the Face layer. - - Only RPC Framework should instantiate and raise these exceptions. - """ - - -class CancellationError(RpcError): - """Indicates that an RPC has been cancelled.""" - - -class ExpirationError(RpcError): - """Indicates that an RPC has expired ("timed out").""" - - -class NetworkError(RpcError): - """Indicates that some error occurred on the network.""" - - -class ServicedError(RpcError): - """Indicates that the Serviced failed in the course of an RPC.""" - - -class ServicerError(RpcError): - """Indicates that the Servicer failed in the course of servicing an RPC.""" diff --git a/src/python/grpcio/grpc/framework/face/implementations.py b/src/python/grpcio/grpc/framework/face/implementations.py deleted file mode 100644 index 96055b4130..0000000000 --- a/src/python/grpcio/grpc/framework/face/implementations.py +++ /dev/null @@ -1,320 +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. - -"""Entry points into the Face layer of RPC Framework.""" - -import six - -from grpc.framework.common import cardinality -from grpc.framework.common import style -from grpc.framework.base import exceptions as _base_exceptions -from grpc.framework.base import interfaces as base_interfaces -from grpc.framework.face import _calls -from grpc.framework.face import _service -from grpc.framework.face import exceptions -from grpc.framework.face import interfaces - - -class _BaseServicer(base_interfaces.Servicer): - - def __init__(self, methods, multi_method): - self._methods = methods - self._multi_method = multi_method - - def service(self, name, context, output_consumer): - method = self._methods.get(name, None) - if method is not None: - return method(output_consumer, context) - elif self._multi_method is not None: - try: - return self._multi_method.service(name, output_consumer, context) - except exceptions.NoSuchMethodError: - raise _base_exceptions.NoSuchMethodError() - else: - raise _base_exceptions.NoSuchMethodError() - - -class _UnaryUnaryMultiCallable(interfaces.UnaryUnaryMultiCallable): - - def __init__(self, front, name): - self._front = front - self._name = name - - def __call__(self, request, timeout): - return _calls.blocking_value_in_value_out( - self._front, self._name, request, timeout, 'unused trace ID') - - def future(self, request, timeout): - return _calls.future_value_in_value_out( - self._front, self._name, request, timeout, 'unused trace ID') - - def event(self, request, response_callback, abortion_callback, timeout): - return _calls.event_value_in_value_out( - self._front, self._name, request, response_callback, abortion_callback, - timeout, 'unused trace ID') - - -class _UnaryStreamMultiCallable(interfaces.UnaryStreamMultiCallable): - - def __init__(self, front, name): - self._front = front - self._name = name - - def __call__(self, request, timeout): - return _calls.inline_value_in_stream_out( - self._front, self._name, request, timeout, 'unused trace ID') - - def event(self, request, response_consumer, abortion_callback, timeout): - return _calls.event_value_in_stream_out( - self._front, self._name, request, response_consumer, abortion_callback, - timeout, 'unused trace ID') - - -class _StreamUnaryMultiCallable(interfaces.StreamUnaryMultiCallable): - - def __init__(self, front, name, pool): - self._front = front - self._name = name - self._pool = pool - - def __call__(self, request_iterator, timeout): - return _calls.blocking_stream_in_value_out( - self._front, self._name, request_iterator, timeout, 'unused trace ID') - - def future(self, request_iterator, timeout): - return _calls.future_stream_in_value_out( - self._front, self._name, request_iterator, timeout, 'unused trace ID', - self._pool) - - def event(self, response_callback, abortion_callback, timeout): - return _calls.event_stream_in_value_out( - self._front, self._name, response_callback, abortion_callback, timeout, - 'unused trace ID') - - -class _StreamStreamMultiCallable(interfaces.StreamStreamMultiCallable): - - def __init__(self, front, name, pool): - self._front = front - self._name = name - self._pool = pool - - def __call__(self, request_iterator, timeout): - return _calls.inline_stream_in_stream_out( - self._front, self._name, request_iterator, timeout, 'unused trace ID', - self._pool) - - def event(self, response_consumer, abortion_callback, timeout): - return _calls.event_stream_in_stream_out( - self._front, self._name, response_consumer, abortion_callback, timeout, - 'unused trace ID') - - -class _GenericStub(interfaces.GenericStub): - """An interfaces.GenericStub implementation.""" - - def __init__(self, front, pool): - self._front = front - self._pool = pool - - def blocking_value_in_value_out(self, name, request, timeout): - return _calls.blocking_value_in_value_out( - self._front, name, request, timeout, 'unused trace ID') - - def future_value_in_value_out(self, name, request, timeout): - return _calls.future_value_in_value_out( - self._front, name, request, timeout, 'unused trace ID') - - def inline_value_in_stream_out(self, name, request, timeout): - return _calls.inline_value_in_stream_out( - self._front, name, request, timeout, 'unused trace ID') - - def blocking_stream_in_value_out(self, name, request_iterator, timeout): - return _calls.blocking_stream_in_value_out( - self._front, name, request_iterator, timeout, 'unused trace ID') - - def future_stream_in_value_out(self, name, request_iterator, timeout): - return _calls.future_stream_in_value_out( - self._front, name, request_iterator, timeout, 'unused trace ID', - self._pool) - - def inline_stream_in_stream_out(self, name, request_iterator, timeout): - return _calls.inline_stream_in_stream_out( - self._front, name, request_iterator, timeout, 'unused trace ID', - self._pool) - - def event_value_in_value_out( - self, name, request, response_callback, abortion_callback, timeout): - return _calls.event_value_in_value_out( - self._front, name, request, response_callback, abortion_callback, - timeout, 'unused trace ID') - - def event_value_in_stream_out( - self, name, request, response_consumer, abortion_callback, timeout): - return _calls.event_value_in_stream_out( - self._front, name, request, response_consumer, abortion_callback, - timeout, 'unused trace ID') - - def event_stream_in_value_out( - self, name, response_callback, abortion_callback, timeout): - return _calls.event_stream_in_value_out( - self._front, name, response_callback, abortion_callback, timeout, - 'unused trace ID') - - def event_stream_in_stream_out( - self, name, response_consumer, abortion_callback, timeout): - return _calls.event_stream_in_stream_out( - self._front, name, response_consumer, abortion_callback, timeout, - 'unused trace ID') - - def unary_unary_multi_callable(self, name): - return _UnaryUnaryMultiCallable(self._front, name) - - def unary_stream_multi_callable(self, name): - return _UnaryStreamMultiCallable(self._front, name) - - def stream_unary_multi_callable(self, name): - return _StreamUnaryMultiCallable(self._front, name, self._pool) - - def stream_stream_multi_callable(self, name): - return _StreamStreamMultiCallable(self._front, name, self._pool) - - -class _DynamicStub(interfaces.DynamicStub): - """An interfaces.DynamicStub implementation.""" - - def __init__(self, cardinalities, front, pool): - self._cardinalities = cardinalities - self._front = front - self._pool = pool - - def __getattr__(self, attr): - method_cardinality = self._cardinalities.get(attr) - if method_cardinality is cardinality.Cardinality.UNARY_UNARY: - return _UnaryUnaryMultiCallable(self._front, attr) - elif method_cardinality is cardinality.Cardinality.UNARY_STREAM: - return _UnaryStreamMultiCallable(self._front, attr) - elif method_cardinality is cardinality.Cardinality.STREAM_UNARY: - return _StreamUnaryMultiCallable(self._front, attr, self._pool) - elif method_cardinality is cardinality.Cardinality.STREAM_STREAM: - return _StreamStreamMultiCallable(self._front, attr, self._pool) - else: - raise AttributeError('_DynamicStub object has no attribute "%s"!' % attr) - - -def _adapt_method_implementations(method_implementations, pool): - adapted_implementations = {} - for name, method_implementation in six.iteritems(method_implementations): - if method_implementation.style is style.Service.INLINE: - if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: - adapted_implementations[name] = _service.adapt_inline_value_in_value_out( - method_implementation.unary_unary_inline) - elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: - adapted_implementations[name] = _service.adapt_inline_value_in_stream_out( - method_implementation.unary_stream_inline) - elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: - adapted_implementations[name] = _service.adapt_inline_stream_in_value_out( - method_implementation.stream_unary_inline, pool) - elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: - adapted_implementations[name] = _service.adapt_inline_stream_in_stream_out( - method_implementation.stream_stream_inline, pool) - elif method_implementation.style is style.Service.EVENT: - if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: - adapted_implementations[name] = _service.adapt_event_value_in_value_out( - method_implementation.unary_unary_event) - elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: - adapted_implementations[name] = _service.adapt_event_value_in_stream_out( - method_implementation.unary_stream_event) - elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: - adapted_implementations[name] = _service.adapt_event_stream_in_value_out( - method_implementation.stream_unary_event) - elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: - adapted_implementations[name] = _service.adapt_event_stream_in_stream_out( - method_implementation.stream_stream_event) - return adapted_implementations - - -def servicer(pool, method_implementations, multi_method_implementation): - """Creates a base_interfaces.Servicer. - - It is guaranteed that any passed interfaces.MultiMethodImplementation will - only be called to service an RPC if there is no - interfaces.MethodImplementation for the RPC method in the passed - method_implementations dictionary. - - Args: - pool: A thread pool. - method_implementations: A dictionary from RPC method name to - interfaces.MethodImplementation object to be used to service the named - RPC method. - multi_method_implementation: An interfaces.MultiMethodImplementation to be - used to service any RPCs not serviced by the - interfaces.MethodImplementations given in the method_implementations - dictionary, or None. - - Returns: - A base_interfaces.Servicer that services RPCs via the given implementations. - """ - adapted_implementations = _adapt_method_implementations( - method_implementations, pool) - return _BaseServicer(adapted_implementations, multi_method_implementation) - - -def generic_stub(front, pool): - """Creates an interfaces.GenericStub. - - Args: - front: A base_interfaces.Front. - pool: A futures.ThreadPoolExecutor. - - Returns: - An interfaces.GenericStub that performs RPCs via the given - base_interfaces.Front. - """ - return _GenericStub(front, pool) - - -def dynamic_stub(cardinalities, front, pool, prefix): - """Creates an interfaces.DynamicStub. - - Args: - cardinalities: A dict from RPC method name to cardinality.Cardinality - value identifying the cardinality of every RPC method to be supported by - the created interfaces.DynamicStub. - front: A base_interfaces.Front. - pool: A futures.ThreadPoolExecutor. - prefix: A string to prepend when mapping requested attribute name to RPC - method name during attribute access on the created - interfaces.DynamicStub. - - Returns: - An interfaces.DynamicStub that performs RPCs via the given - base_interfaces.Front. - """ - return _DynamicStub(cardinalities, front, pool) diff --git a/src/python/grpcio/grpc/framework/face/interfaces.py b/src/python/grpcio/grpc/framework/face/interfaces.py deleted file mode 100644 index e9a25c17e1..0000000000 --- a/src/python/grpcio/grpc/framework/face/interfaces.py +++ /dev/null @@ -1,634 +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. - -"""Interfaces for the face layer of RPC Framework.""" - -import abc -import enum - -import six - -# cardinality, style, exceptions, abandonment, future, and stream are -# referenced from specification in this module. -from grpc.framework.common import cardinality # pylint: disable=unused-import -from grpc.framework.common import style # pylint: disable=unused-import -from grpc.framework.face import exceptions # pylint: disable=unused-import -from grpc.framework.foundation import abandonment # pylint: disable=unused-import -from grpc.framework.foundation import future # pylint: disable=unused-import -from grpc.framework.foundation import stream # pylint: disable=unused-import - - -@enum.unique -class Abortion(enum.Enum): - """Categories of RPC abortion.""" - CANCELLED = 'cancelled' - EXPIRED = 'expired' - NETWORK_FAILURE = 'network failure' - SERVICED_FAILURE = 'serviced failure' - SERVICER_FAILURE = 'servicer failure' - - -class CancellableIterator(six.with_metaclass(abc.ABCMeta)): - """Implements the Iterator protocol and affords a cancel method.""" - - @abc.abstractmethod - def __iter__(self): - """Returns the self object in accordance with the Iterator protocol.""" - raise NotImplementedError() - - def __next__(self): - return self.next() - - @abc.abstractmethod - def next(self): - """Returns a value or raises StopIteration per the Iterator protocol.""" - raise NotImplementedError() - - @abc.abstractmethod - def cancel(self): - """Requests cancellation of whatever computation underlies this iterator.""" - raise NotImplementedError() - - -class RpcContext(six.with_metaclass(abc.ABCMeta)): - """Provides RPC-related information and action.""" - - @abc.abstractmethod - def is_active(self): - """Describes whether the RPC is active or has terminated.""" - raise NotImplementedError() - - @abc.abstractmethod - def time_remaining(self): - """Describes the length of allowed time remaining for the RPC. - - Returns: - A nonnegative float indicating the length of allowed time in seconds - remaining for the RPC to complete before it is considered to have timed - out. - """ - raise NotImplementedError() - - @abc.abstractmethod - def add_abortion_callback(self, abortion_callback): - """Registers a callback to be called if the RPC is aborted. - - Args: - abortion_callback: A callable to be called and passed an Abortion value - in the event of RPC abortion. - """ - raise NotImplementedError() - - -class Call(six.with_metaclass(abc.ABCMeta)): - """Invocation-side representation of an RPC. - - Attributes: - context: An RpcContext affording information about the RPC. - """ - - @abc.abstractmethod - def cancel(self): - """Requests cancellation of the RPC.""" - raise NotImplementedError() - - -class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a unary-unary RPC in any call style.""" - - @abc.abstractmethod - def __call__(self, request, timeout): - """Synchronously invokes the underlying RPC. - - Args: - request: The request value for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - The response value for the RPC. - - Raises: - exceptions.RpcError: Indicating that the RPC was aborted. - """ - raise NotImplementedError() - - @abc.abstractmethod - def future(self, request, timeout): - """Asynchronously invokes the underlying RPC. - - Args: - request: The request value for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A future.Future representing the RPC. In the event of RPC completion, the - returned Future's result value will be the response value of the RPC. - In the event of RPC abortion, the returned Future's exception value - will be an exceptions.RpcError. - """ - raise NotImplementedError() - - @abc.abstractmethod - def event(self, request, response_callback, abortion_callback, timeout): - """Asynchronously invokes the underlying RPC. - - Args: - request: The request value for the RPC. - response_callback: A callback to be called to accept the restponse value - of the RPC. - abortion_callback: A callback to be called and passed an Abortion value - in the event of RPC abortion. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A Call object for the RPC. - """ - raise NotImplementedError() - - -class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a unary-stream RPC in any call style.""" - - @abc.abstractmethod - def __call__(self, request, timeout): - """Synchronously invokes the underlying RPC. - - Args: - request: The request value for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A CancellableIterator that yields the response values of the RPC and - affords RPC cancellation. Drawing response values from the returned - CancellableIterator may raise exceptions.RpcError indicating abortion - of the RPC. - """ - raise NotImplementedError() - - @abc.abstractmethod - def event(self, request, response_consumer, abortion_callback, timeout): - """Asynchronously invokes the underlying RPC. - - Args: - request: The request value for the RPC. - response_consumer: A stream.Consumer to be called to accept the restponse - values of the RPC. - abortion_callback: A callback to be called and passed an Abortion value - in the event of RPC abortion. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A Call object for the RPC. - """ - raise NotImplementedError() - - -class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a stream-unary RPC in any call style.""" - - @abc.abstractmethod - def __call__(self, request_iterator, timeout): - """Synchronously invokes the underlying RPC. - - Args: - request_iterator: An iterator that yields request values for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - The response value for the RPC. - - Raises: - exceptions.RpcError: Indicating that the RPC was aborted. - """ - raise NotImplementedError() - - @abc.abstractmethod - def future(self, request_iterator, timeout): - """Asynchronously invokes the underlying RPC. - - Args: - request_iterator: An iterator that yields request values for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A future.Future representing the RPC. In the event of RPC completion, the - returned Future's result value will be the response value of the RPC. - In the event of RPC abortion, the returned Future's exception value - will be an exceptions.RpcError. - """ - raise NotImplementedError() - - @abc.abstractmethod - def event(self, response_callback, abortion_callback, timeout): - """Asynchronously invokes the underlying RPC. - - Args: - request: The request value for the RPC. - response_callback: A callback to be called to accept the restponse value - of the RPC. - abortion_callback: A callback to be called and passed an Abortion value - in the event of RPC abortion. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A pair of a Call object for the RPC and a stream.Consumer to which the - request values of the RPC should be passed. - """ - raise NotImplementedError() - - -class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a stream-stream RPC in any call style.""" - - @abc.abstractmethod - def __call__(self, request_iterator, timeout): - """Synchronously invokes the underlying RPC. - - Args: - request_iterator: An iterator that yields request values for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A CancellableIterator that yields the response values of the RPC and - affords RPC cancellation. Drawing response values from the returned - CancellableIterator may raise exceptions.RpcError indicating abortion - of the RPC. - """ - raise NotImplementedError() - - @abc.abstractmethod - def event(self, response_consumer, abortion_callback, timeout): - """Asynchronously invokes the underlying RPC. - -l Args: - response_consumer: A stream.Consumer to be called to accept the restponse - values of the RPC. - abortion_callback: A callback to be called and passed an Abortion value - in the event of RPC abortion. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A pair of a Call object for the RPC and a stream.Consumer to which the - request values of the RPC should be passed. - """ - raise NotImplementedError() - - -class MethodImplementation(six.with_metaclass(abc.ABCMeta)): - """A sum type that describes an RPC method implementation. - - Attributes: - cardinality: A cardinality.Cardinality value. - style: A style.Service value. - unary_unary_inline: The implementation of the RPC method as a callable - value that takes a request value and an RpcContext object and returns a - response value. Only non-None if cardinality is - cardinality.Cardinality.UNARY_UNARY and style is style.Service.INLINE. - unary_stream_inline: The implementation of the RPC method as a callable - value that takes a request value and an RpcContext object and returns an - iterator of response values. Only non-None if cardinality is - cardinality.Cardinality.UNARY_STREAM and style is style.Service.INLINE. - stream_unary_inline: The implementation of the RPC method as a callable - value that takes an iterator of request values and an RpcContext object - and returns a response value. Only non-None if cardinality is - cardinality.Cardinality.STREAM_UNARY and style is style.Service.INLINE. - stream_stream_inline: The implementation of the RPC method as a callable - value that takes an iterator of request values and an RpcContext object - and returns an iterator of response values. Only non-None if cardinality - is cardinality.Cardinality.STREAM_STREAM and style is - style.Service.INLINE. - unary_unary_event: The implementation of the RPC method as a callable value - that takes a request value, a response callback to which to pass the - response value of the RPC, and an RpcContext. Only non-None if - cardinality is cardinality.Cardinality.UNARY_UNARY and style is - style.Service.EVENT. - unary_stream_event: The implementation of the RPC method as a callable - value that takes a request value, a stream.Consumer to which to pass the - the response values of the RPC, and an RpcContext. Only non-None if - cardinality is cardinality.Cardinality.UNARY_STREAM and style is - style.Service.EVENT. - stream_unary_event: The implementation of the RPC method as a callable - value that takes a response callback to which to pass the response value - of the RPC and an RpcContext and returns a stream.Consumer to which the - request values of the RPC should be passed. Only non-None if cardinality - is cardinality.Cardinality.STREAM_UNARY and style is style.Service.EVENT. - stream_stream_event: The implementation of the RPC method as a callable - value that takes a stream.Consumer to which to pass the response values - of the RPC and an RpcContext and returns a stream.Consumer to which the - request values of the RPC should be passed. Only non-None if cardinality - is cardinality.Cardinality.STREAM_STREAM and style is - style.Service.EVENT. - """ - - -class MultiMethodImplementation(six.with_metaclass(abc.ABCMeta)): - """A general type able to service many RPC methods.""" - - @abc.abstractmethod - def service(self, name, response_consumer, context): - """Services an RPC. - - Args: - name: The RPC method name. - response_consumer: A stream.Consumer to be called to accept the response - values of the RPC. - context: An RpcContext object. - - Returns: - A stream.Consumer with which to accept the request values of the RPC. The - consumer returned from this method may or may not be invoked to - completion: in the case of RPC abortion, RPC Framework will simply stop - passing values to this object. Implementations must not assume that this - object will be called to completion of the request stream or even called - at all. - - Raises: - abandonment.Abandoned: May or may not be raised when the RPC has been - aborted. - exceptions.NoSuchMethodError: If this MultiMethod does not recognize the - given RPC method name and is not able to service the RPC. - """ - raise NotImplementedError() - - -class GenericStub(six.with_metaclass(abc.ABCMeta)): - """Affords RPC methods to callers.""" - - @abc.abstractmethod - def blocking_value_in_value_out(self, name, request, timeout): - """Invokes a unary-request-unary-response RPC method. - - This method blocks until either returning the response value of the RPC - (in the event of RPC completion) or raising an exception (in the event of - RPC abortion). - - Args: - name: The RPC method name. - request: The request value for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - The response value for the RPC. - - Raises: - exceptions.RpcError: Indicating that the RPC was aborted. - """ - raise NotImplementedError() - - @abc.abstractmethod - def future_value_in_value_out(self, name, request, timeout): - """Invokes a unary-request-unary-response RPC method. - - Args: - name: The RPC method name. - request: The request value for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A future.Future representing the RPC. In the event of RPC completion, the - returned Future will return an outcome indicating that the RPC returned - the response value of the RPC. In the event of RPC abortion, the - returned Future will return an outcome indicating that the RPC raised - an exceptions.RpcError. - """ - raise NotImplementedError() - - @abc.abstractmethod - def inline_value_in_stream_out(self, name, request, timeout): - """Invokes a unary-request-stream-response RPC method. - - Args: - name: The RPC method name. - request: The request value for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A CancellableIterator that yields the response values of the RPC and - affords RPC cancellation. Drawing response values from the returned - CancellableIterator may raise exceptions.RpcError indicating abortion of - the RPC. - """ - raise NotImplementedError() - - @abc.abstractmethod - def blocking_stream_in_value_out(self, name, request_iterator, timeout): - """Invokes a stream-request-unary-response RPC method. - - This method blocks until either returning the response value of the RPC - (in the event of RPC completion) or raising an exception (in the event of - RPC abortion). - - Args: - name: The RPC method name. - request_iterator: An iterator that yields the request values of the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - The response value for the RPC. - - Raises: - exceptions.RpcError: Indicating that the RPC was aborted. - """ - raise NotImplementedError() - - @abc.abstractmethod - def future_stream_in_value_out(self, name, request_iterator, timeout): - """Invokes a stream-request-unary-response RPC method. - - Args: - name: The RPC method name. - request_iterator: An iterator that yields the request values of the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A future.Future representing the RPC. In the event of RPC completion, the - returned Future will return an outcome indicating that the RPC returned - the response value of the RPC. In the event of RPC abortion, the - returned Future will return an outcome indicating that the RPC raised - an exceptions.RpcError. - """ - raise NotImplementedError() - - @abc.abstractmethod - def inline_stream_in_stream_out(self, name, request_iterator, timeout): - """Invokes a stream-request-stream-response RPC method. - - Args: - name: The RPC method name. - request_iterator: An iterator that yields the request values of the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A CancellableIterator that yields the response values of the RPC and - affords RPC cancellation. Drawing response values from the returned - CancellableIterator may raise exceptions.RpcError indicating abortion of - the RPC. - """ - raise NotImplementedError() - - @abc.abstractmethod - def event_value_in_value_out( - self, name, request, response_callback, abortion_callback, timeout): - """Event-driven invocation of a unary-request-unary-response RPC method. - - Args: - name: The RPC method name. - request: The request value for the RPC. - response_callback: A callback to be called to accept the response value - of the RPC. - abortion_callback: A callback to be called and passed an Abortion value - in the event of RPC abortion. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A Call object for the RPC. - """ - raise NotImplementedError() - - @abc.abstractmethod - def event_value_in_stream_out( - self, name, request, response_consumer, abortion_callback, timeout): - """Event-driven invocation of a unary-request-stream-response RPC method. - - Args: - name: The RPC method name. - request: The request value for the RPC. - response_consumer: A stream.Consumer to be called to accept the response - values of the RPC. - abortion_callback: A callback to be called and passed an Abortion value - in the event of RPC abortion. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A Call object for the RPC. - """ - raise NotImplementedError() - - @abc.abstractmethod - def event_stream_in_value_out( - self, name, response_callback, abortion_callback, timeout): - """Event-driven invocation of a unary-request-unary-response RPC method. - - Args: - name: The RPC method name. - response_callback: A callback to be called to accept the response value - of the RPC. - abortion_callback: A callback to be called and passed an Abortion value - in the event of RPC abortion. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A pair of a Call object for the RPC and a stream.Consumer to which the - request values of the RPC should be passed. - """ - raise NotImplementedError() - - @abc.abstractmethod - def event_stream_in_stream_out( - self, name, response_consumer, abortion_callback, timeout): - """Event-driven invocation of a unary-request-stream-response RPC method. - - Args: - name: The RPC method name. - response_consumer: A stream.Consumer to be called to accept the response - values of the RPC. - abortion_callback: A callback to be called and passed an Abortion value - in the event of RPC abortion. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A pair of a Call object for the RPC and a stream.Consumer to which the - request values of the RPC should be passed. - """ - raise NotImplementedError() - - @abc.abstractmethod - def unary_unary_multi_callable(self, name): - """Creates a UnaryUnaryMultiCallable for a unary-unary RPC method. - - Args: - name: The RPC method name. - - Returns: - A UnaryUnaryMultiCallable value for the named unary-unary RPC method. - """ - raise NotImplementedError() - - @abc.abstractmethod - def unary_stream_multi_callable(self, name): - """Creates a UnaryStreamMultiCallable for a unary-stream RPC method. - - Args: - name: The RPC method name. - - Returns: - A UnaryStreamMultiCallable value for the name unary-stream RPC method. - """ - raise NotImplementedError() - - @abc.abstractmethod - def stream_unary_multi_callable(self, name): - """Creates a StreamUnaryMultiCallable for a stream-unary RPC method. - - Args: - name: The RPC method name. - - Returns: - A StreamUnaryMultiCallable value for the named stream-unary RPC method. - """ - raise NotImplementedError() - - @abc.abstractmethod - def stream_stream_multi_callable(self, name): - """Creates a StreamStreamMultiCallable for a stream-stream RPC method. - - Args: - name: The RPC method name. - - Returns: - A StreamStreamMultiCallable value for the named stream-stream RPC method. - """ - raise NotImplementedError() - - -class DynamicStub(six.with_metaclass(abc.ABCMeta)): - """A stub with RPC-method-bound multi-callable attributes. - - Instances of this type responsd to attribute access as follows: if the - requested attribute is the name of a unary-unary RPC method, the value of the - attribute will be a UnaryUnaryMultiCallable with which to invoke the RPC - method; if the requested attribute is the name of a unary-stream RPC method, - the value of the attribute will be a UnaryStreamMultiCallable with which to - invoke the RPC method; if the requested attribute is the name of a - stream-unary RPC method, the value of the attribute will be a - StreamUnaryMultiCallable with which to invoke the RPC method; and if the - requested attribute is the name of a stream-stream RPC method, the value of - the attribute will be a StreamStreamMultiCallable with which to invoke the - RPC method. - """ diff --git a/src/python/grpcio/grpc/framework/face/utilities.py b/src/python/grpcio/grpc/framework/face/utilities.py deleted file mode 100644 index a63fe8c60d..0000000000 --- a/src/python/grpcio/grpc/framework/face/utilities.py +++ /dev/null @@ -1,177 +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. - -"""Utilities for RPC framework's face layer.""" - -import collections - -from grpc.framework.common import cardinality -from grpc.framework.common import style -from grpc.framework.face import interfaces -from grpc.framework.foundation import stream - - -class _MethodImplementation( - interfaces.MethodImplementation, - collections.namedtuple( - '_MethodImplementation', - ['cardinality', 'style', 'unary_unary_inline', 'unary_stream_inline', - 'stream_unary_inline', 'stream_stream_inline', 'unary_unary_event', - 'unary_stream_event', 'stream_unary_event', 'stream_stream_event',])): - pass - - -def unary_unary_inline(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a unary-unary RPC method as a callable value - that takes a request value and an interfaces.RpcContext object and - returns a response value. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_UNARY, style.Service.INLINE, behavior, - None, None, None, None, None, None, None) - - -def unary_stream_inline(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a unary-stream RPC method as a callable - value that takes a request value and an interfaces.RpcContext object and - returns an iterator of response values. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_STREAM, style.Service.INLINE, None, - behavior, None, None, None, None, None, None) - - -def stream_unary_inline(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a stream-unary RPC method as a callable - value that takes an iterator of request values and an - interfaces.RpcContext object and returns a response value. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_UNARY, style.Service.INLINE, None, None, - behavior, None, None, None, None, None) - - -def stream_stream_inline(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a stream-stream RPC method as a callable - value that takes an iterator of request values and an - interfaces.RpcContext object and returns an iterator of response values. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_STREAM, style.Service.INLINE, None, None, - None, behavior, None, None, None, None) - - -def unary_unary_event(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a unary-unary RPC method as a callable - value that takes a request value, a response callback to which to pass - the response value of the RPC, and an interfaces.RpcContext. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_UNARY, style.Service.EVENT, None, None, - None, None, behavior, None, None, None) - - -def unary_stream_event(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a unary-stream RPC method as a callable - value that takes a request value, a stream.Consumer to which to pass the - the response values of the RPC, and an interfaces.RpcContext. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_STREAM, style.Service.EVENT, None, None, - None, None, None, behavior, None, None) - - -def stream_unary_event(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a stream-unary RPC method as a callable - value that takes a response callback to which to pass the response value - of the RPC and an interfaces.RpcContext and returns a stream.Consumer to - which the request values of the RPC should be passed. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_UNARY, style.Service.EVENT, None, None, - None, None, None, None, behavior, None) - - -def stream_stream_event(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a stream-stream RPC method as a callable - value that takes a stream.Consumer to which to pass the response values - of the RPC and an interfaces.RpcContext and returns a stream.Consumer to - which the request values of the RPC should be passed. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_STREAM, style.Service.EVENT, None, None, - None, None, None, None, None, behavior) diff --git a/src/python/grpcio/tests/unit/framework/face/__init__.py b/src/python/grpcio/tests/unit/framework/face/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/__init__.py +++ /dev/null @@ -1,30 +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. - - diff --git a/src/python/grpcio/tests/unit/framework/face/testing/__init__.py b/src/python/grpcio/tests/unit/framework/face/testing/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/__init__.py +++ /dev/null @@ -1,30 +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. - - diff --git a/src/python/grpcio/tests/unit/framework/face/testing/base_util.py b/src/python/grpcio/tests/unit/framework/face/testing/base_util.py deleted file mode 100644 index 59652b3e90..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/base_util.py +++ /dev/null @@ -1,102 +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. - -"""Utilities for creating Base-layer objects for use in Face-layer tests.""" - -import abc - -import six - -# interfaces is referenced from specification in this module. -from grpc.framework.base import util as _base_util -from grpc.framework.base import implementations -from grpc.framework.base import in_memory -from grpc.framework.base import interfaces # pylint: disable=unused-import -from grpc.framework.foundation import logging_pool - -_POOL_SIZE_LIMIT = 5 - -_MAXIMUM_TIMEOUT = 90 - - -class LinkedPair(six.with_metaclass(abc.ABCMeta)): - """A Front and Back that are linked to one another. - - Attributes: - front: An interfaces.Front. - back: An interfaces.Back. - """ - - @abc.abstractmethod - def shut_down(self): - """Shuts down this object and releases its resources.""" - raise NotImplementedError() - - -class _LinkedPair(LinkedPair): - - def __init__(self, front, back, pools): - self.front = front - self.back = back - self._pools = pools - - def shut_down(self): - _base_util.wait_for_idle(self.front) - _base_util.wait_for_idle(self.back) - - for pool in self._pools: - pool.shutdown(wait=True) - - -def linked_pair(servicer, default_timeout): - """Creates a Server and Stub linked together for use.""" - link_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - front_work_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - front_transmission_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - front_utility_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - back_work_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - back_transmission_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - back_utility_pool = logging_pool.pool(_POOL_SIZE_LIMIT) - pools = ( - link_pool, - front_work_pool, front_transmission_pool, front_utility_pool, - back_work_pool, back_transmission_pool, back_utility_pool) - - link = in_memory.Link(link_pool) - front = implementations.front_link( - front_work_pool, front_transmission_pool, front_utility_pool) - back = implementations.back_link( - servicer, back_work_pool, back_transmission_pool, back_utility_pool, - default_timeout, _MAXIMUM_TIMEOUT) - front.join_rear_link(link) - link.join_fore_link(front) - back.join_fore_link(link) - link.join_rear_link(back) - - return _LinkedPair(front, back, pools) diff --git a/src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py deleted file mode 100644 index 2ebe1a32a4..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/blocking_invocation_inline_service_test_case.py +++ /dev/null @@ -1,224 +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. - -"""A test to verify an implementation of the Face layer of RPC Framework.""" - -# unittest is referenced from specification in this module. -import abc -import unittest # pylint: disable=unused-import - -import six - -from grpc.framework.face import exceptions -from tests.unit.framework.common import test_constants -from tests.unit.framework.face.testing import control -from tests.unit.framework.face.testing import coverage -from tests.unit.framework.face.testing import digest -from tests.unit.framework.face.testing import stock_service -from tests.unit.framework.face.testing import test_case - - -class BlockingInvocationInlineServiceTestCase( - six.with_metaclass(abc.ABCMeta, - test_case.FaceTestCase, coverage.BlockingCoverage)): - """A test of the Face layer of RPC Framework. - - Concrete subclasses must also extend unittest.TestCase. - """ - - def setUp(self): - """See unittest.TestCase.setUp for full specification. - - Overriding implementations must call this implementation. - """ - self.control = control.PauseFailControl() - self.digest = digest.digest( - stock_service.STOCK_TEST_SERVICE, self.control, None) - - self.stub, self.memo = self.set_up_implementation( - self.digest.name, self.digest.methods, - self.digest.inline_method_implementations, None) - - def tearDown(self): - """See unittest.TestCase.tearDown for full specification. - - Overriding implementations must call this implementation. - """ - self.tear_down_implementation(self.memo) - - def testSuccessfulUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - response = self.stub.blocking_value_in_value_out( - name, request, test_constants.LONG_TIMEOUT) - - test_messages.verify(request, response, self) - - def testSuccessfulUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - response_iterator = self.stub.inline_value_in_stream_out( - name, request, test_constants.LONG_TIMEOUT) - responses = list(response_iterator) - - test_messages.verify(request, responses, self) - - def testSuccessfulStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - response = self.stub.blocking_stream_in_value_out( - name, iter(requests), test_constants.LONG_TIMEOUT) - - test_messages.verify(requests, response, self) - - def testSuccessfulStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - response_iterator = self.stub.inline_stream_in_stream_out( - name, iter(requests), test_constants.LONG_TIMEOUT) - responses = list(response_iterator) - - test_messages.verify(requests, responses, self) - - def testSequentialInvocations(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - first_request = test_messages.request() - second_request = test_messages.request() - - first_response = self.stub.blocking_value_in_value_out( - name, first_request, test_constants.SHORT_TIMEOUT) - - test_messages.verify(first_request, first_response, self) - - second_response = self.stub.blocking_value_in_value_out( - name, second_request, test_constants.SHORT_TIMEOUT) - - test_messages.verify(second_request, second_response, self) - - def testExpiredUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self.control.pause(), self.assertRaises( - exceptions.ExpirationError): - multi_callable = self.stub.unary_unary_multi_callable(name) - multi_callable(request, test_constants.SHORT_TIMEOUT) - - def testExpiredUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self.control.pause(), self.assertRaises( - exceptions.ExpirationError): - response_iterator = self.stub.inline_value_in_stream_out( - name, request, test_constants.SHORT_TIMEOUT) - list(response_iterator) - - def testExpiredStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self.control.pause(), self.assertRaises( - exceptions.ExpirationError): - multi_callable = self.stub.stream_unary_multi_callable(name) - multi_callable(iter(requests), test_constants.SHORT_TIMEOUT) - - def testExpiredStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self.control.pause(), self.assertRaises( - exceptions.ExpirationError): - response_iterator = self.stub.inline_stream_in_stream_out( - name, iter(requests), test_constants.SHORT_TIMEOUT) - list(response_iterator) - - def testFailedUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self.control.fail(), self.assertRaises(exceptions.ServicerError): - self.stub.blocking_value_in_value_out(name, request, - test_constants.SHORT_TIMEOUT) - - def testFailedUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self.control.fail(), self.assertRaises(exceptions.ServicerError): - response_iterator = self.stub.inline_value_in_stream_out( - name, request, test_constants.SHORT_TIMEOUT) - list(response_iterator) - - def testFailedStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self.control.fail(), self.assertRaises(exceptions.ServicerError): - self.stub.blocking_stream_in_value_out(name, iter(requests), - test_constants.SHORT_TIMEOUT) - - def testFailedStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self.control.fail(), self.assertRaises(exceptions.ServicerError): - response_iterator = self.stub.inline_stream_in_stream_out( - name, iter(requests), test_constants.SHORT_TIMEOUT) - list(response_iterator) diff --git a/src/python/grpcio/tests/unit/framework/face/testing/callback.py b/src/python/grpcio/tests/unit/framework/face/testing/callback.py deleted file mode 100644 index d0e63c8c56..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/callback.py +++ /dev/null @@ -1,94 +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. - -"""A utility useful in tests of asynchronous, event-driven interfaces.""" - -import threading - -from grpc.framework.foundation import stream - - -class Callback(stream.Consumer): - """A utility object useful in tests of asynchronous code.""" - - def __init__(self): - self._condition = threading.Condition() - self._unary_response = None - self._streamed_responses = [] - self._completed = False - self._abortion = None - - def abort(self, abortion): - with self._condition: - self._abortion = abortion - self._condition.notify_all() - - def complete(self, unary_response): - with self._condition: - self._unary_response = unary_response - self._completed = True - self._condition.notify_all() - - def consume(self, streamed_response): - with self._condition: - self._streamed_responses.append(streamed_response) - - def terminate(self): - with self._condition: - self._completed = True - self._condition.notify_all() - - def consume_and_terminate(self, streamed_response): - with self._condition: - self._streamed_responses.append(streamed_response) - self._completed = True - self._condition.notify_all() - - def block_until_terminated(self): - with self._condition: - while self._abortion is None and not self._completed: - self._condition.wait() - - def response(self): - with self._condition: - if self._abortion is None: - return self._unary_response - else: - raise AssertionError('Aborted with abortion "%s"!' % self._abortion) - - def responses(self): - with self._condition: - if self._abortion is None: - return list(self._streamed_responses) - else: - raise AssertionError('Aborted with abortion "%s"!' % self._abortion) - - def abortion(self): - with self._condition: - return self._abortion diff --git a/src/python/grpcio/tests/unit/framework/face/testing/control.py b/src/python/grpcio/tests/unit/framework/face/testing/control.py deleted file mode 100644 index 8425affcc9..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/control.py +++ /dev/null @@ -1,87 +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. - -"""Code for instructing systems under test to block or fail.""" - -import abc -import contextlib -import threading - -import six - - -class Control(six.with_metaclass(abc.ABCMeta)): - """An object that accepts program control from a system under test. - - Systems under test passed a Control should call its control() method - frequently during execution. The control() method may block, raise an - exception, or do nothing, all according to the enclosing test's desire for - the system under test to simulate hanging, failing, or functioning. - """ - - @abc.abstractmethod - def control(self): - """Potentially does anything.""" - raise NotImplementedError() - - -class PauseFailControl(Control): - """A Control that can be used to pause or fail code under control.""" - - def __init__(self): - self._condition = threading.Condition() - self._paused = False - self._fail = False - - def control(self): - with self._condition: - if self._fail: - raise ValueError() - - while self._paused: - self._condition.wait() - - @contextlib.contextmanager - def pause(self): - """Pauses code under control while controlling code is in context.""" - with self._condition: - self._paused = True - yield - with self._condition: - self._paused = False - self._condition.notify_all() - - @contextlib.contextmanager - def fail(self): - """Fails code under control while controlling code is in context.""" - with self._condition: - self._fail = True - yield - with self._condition: - self._fail = False diff --git a/src/python/grpcio/tests/unit/framework/face/testing/coverage.py b/src/python/grpcio/tests/unit/framework/face/testing/coverage.py deleted file mode 100644 index 3c88b7841a..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/coverage.py +++ /dev/null @@ -1,121 +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. - -"""Governs coverage for the tests of the Face layer of RPC Framework.""" - -import abc - -import six - -# These classes are only valid when inherited by unittest.TestCases. -# pylint: disable=invalid-name - - -class BlockingCoverage(six.with_metaclass(abc.ABCMeta)): - """Specification of test coverage for blocking behaviors.""" - - @abc.abstractmethod - def testSuccessfulUnaryRequestUnaryResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testSuccessfulUnaryRequestStreamResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testSuccessfulStreamRequestUnaryResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testSuccessfulStreamRequestStreamResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testSequentialInvocations(self): - raise NotImplementedError() - - @abc.abstractmethod - def testExpiredUnaryRequestUnaryResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testExpiredUnaryRequestStreamResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testExpiredStreamRequestUnaryResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testExpiredStreamRequestStreamResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testFailedUnaryRequestUnaryResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testFailedUnaryRequestStreamResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testFailedStreamRequestUnaryResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testFailedStreamRequestStreamResponse(self): - raise NotImplementedError() - - -class FullCoverage(six.with_metaclass(abc.ABCMeta, BlockingCoverage)): - """Specification of test coverage for non-blocking behaviors.""" - - @abc.abstractmethod - def testParallelInvocations(self): - raise NotImplementedError() - - @abc.abstractmethod - def testWaitingForSomeButNotAllParallelInvocations(self): - raise NotImplementedError() - - @abc.abstractmethod - def testCancelledUnaryRequestUnaryResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testCancelledUnaryRequestStreamResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testCancelledStreamRequestUnaryResponse(self): - raise NotImplementedError() - - @abc.abstractmethod - def testCancelledStreamRequestStreamResponse(self): - raise NotImplementedError() diff --git a/src/python/grpcio/tests/unit/framework/face/testing/digest.py b/src/python/grpcio/tests/unit/framework/face/testing/digest.py deleted file mode 100644 index 2b45aded20..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/digest.py +++ /dev/null @@ -1,452 +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. - -"""Code for making a service.TestService more amenable to use in tests.""" - -import collections -import threading - -import six - -# testing_control, interfaces, and testing_service are referenced from -# specification in this module. -from grpc.framework.common import cardinality -from grpc.framework.common import style -from grpc.framework.face import exceptions -from grpc.framework.face import interfaces as face_interfaces -from grpc.framework.foundation import stream -from grpc.framework.foundation import stream_util -from tests.unit.framework.face.testing import control as testing_control # pylint: disable=unused-import -from tests.unit.framework.face.testing import interfaces # pylint: disable=unused-import -from tests.unit.framework.face.testing import service as testing_service # pylint: disable=unused-import - -_IDENTITY = lambda x: x - - -class TestServiceDigest( - collections.namedtuple( - 'TestServiceDigest', - ['name', - 'methods', - 'inline_method_implementations', - 'event_method_implementations', - 'multi_method_implementation', - 'unary_unary_messages_sequences', - 'unary_stream_messages_sequences', - 'stream_unary_messages_sequences', - 'stream_stream_messages_sequences'])): - """A transformation of a service.TestService. - - Attributes: - name: The RPC service name to be used in the test. - methods: A sequence of interfaces.Method objects describing the RPC - methods that will be called during the test. - inline_method_implementations: A dict from RPC method name to - face_interfaces.MethodImplementation object to be used in tests of - in-line calls to behaviors under test. - event_method_implementations: A dict from RPC method name to - face_interfaces.MethodImplementation object to be used in tests of - event-driven calls to behaviors under test. - multi_method_implementation: A face_interfaces.MultiMethodImplementation to - be used in tests of generic calls to behaviors under test. - unary_unary_messages_sequences: A dict from method name to sequence of - service.UnaryUnaryTestMessages objects to be used to test the method - with the given name. - unary_stream_messages_sequences: A dict from method name to sequence of - service.UnaryStreamTestMessages objects to be used to test the method - with the given name. - stream_unary_messages_sequences: A dict from method name to sequence of - service.StreamUnaryTestMessages objects to be used to test the method - with the given name. - stream_stream_messages_sequences: A dict from method name to sequence of - service.StreamStreamTestMessages objects to be used to test the - method with the given name. - serialization: A serial.Serialization object describing serialization - behaviors for all the RPC methods. - """ - - -class _BufferingConsumer(stream.Consumer): - """A trivial Consumer that dumps what it consumes in a user-mutable buffer.""" - - def __init__(self): - self.consumed = [] - self.terminated = False - - def consume(self, value): - self.consumed.append(value) - - def terminate(self): - self.terminated = True - - def consume_and_terminate(self, value): - self.consumed.append(value) - self.terminated = True - - -class _InlineUnaryUnaryMethod(face_interfaces.MethodImplementation): - - def __init__(self, unary_unary_test_method, control): - self._test_method = unary_unary_test_method - self._control = control - - self.cardinality = cardinality.Cardinality.UNARY_UNARY - self.style = style.Service.INLINE - - def unary_unary_inline(self, request, context): - response_list = [] - self._test_method.service( - request, response_list.append, context, self._control) - return response_list.pop(0) - - -class _EventUnaryUnaryMethod(face_interfaces.MethodImplementation): - - def __init__(self, unary_unary_test_method, control, pool): - self._test_method = unary_unary_test_method - self._control = control - self._pool = pool - - self.cardinality = cardinality.Cardinality.UNARY_UNARY - self.style = style.Service.EVENT - - def unary_unary_event(self, request, response_callback, context): - if self._pool is None: - self._test_method.service( - request, response_callback, context, self._control) - else: - self._pool.submit( - self._test_method.service, request, response_callback, context, - self._control) - - -class _InlineUnaryStreamMethod(face_interfaces.MethodImplementation): - - def __init__(self, unary_stream_test_method, control): - self._test_method = unary_stream_test_method - self._control = control - - self.cardinality = cardinality.Cardinality.UNARY_STREAM - self.style = style.Service.INLINE - - def unary_stream_inline(self, request, context): - response_consumer = _BufferingConsumer() - self._test_method.service( - request, response_consumer, context, self._control) - for response in response_consumer.consumed: - yield response - - -class _EventUnaryStreamMethod(face_interfaces.MethodImplementation): - - def __init__(self, unary_stream_test_method, control, pool): - self._test_method = unary_stream_test_method - self._control = control - self._pool = pool - - self.cardinality = cardinality.Cardinality.UNARY_STREAM - self.style = style.Service.EVENT - - def unary_stream_event(self, request, response_consumer, context): - if self._pool is None: - self._test_method.service( - request, response_consumer, context, self._control) - else: - self._pool.submit( - self._test_method.service, request, response_consumer, context, - self._control) - - -class _InlineStreamUnaryMethod(face_interfaces.MethodImplementation): - - def __init__(self, stream_unary_test_method, control): - self._test_method = stream_unary_test_method - self._control = control - - self.cardinality = cardinality.Cardinality.STREAM_UNARY - self.style = style.Service.INLINE - - def stream_unary_inline(self, request_iterator, context): - response_list = [] - request_consumer = self._test_method.service( - response_list.append, context, self._control) - for request in request_iterator: - request_consumer.consume(request) - request_consumer.terminate() - return response_list.pop(0) - - -class _EventStreamUnaryMethod(face_interfaces.MethodImplementation): - - def __init__(self, stream_unary_test_method, control, pool): - self._test_method = stream_unary_test_method - self._control = control - self._pool = pool - - self.cardinality = cardinality.Cardinality.STREAM_UNARY - self.style = style.Service.EVENT - - def stream_unary_event(self, response_callback, context): - request_consumer = self._test_method.service( - response_callback, context, self._control) - if self._pool is None: - return request_consumer - else: - return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool) - - -class _InlineStreamStreamMethod(face_interfaces.MethodImplementation): - - def __init__(self, stream_stream_test_method, control): - self._test_method = stream_stream_test_method - self._control = control - - self.cardinality = cardinality.Cardinality.STREAM_STREAM - self.style = style.Service.INLINE - - def stream_stream_inline(self, request_iterator, context): - response_consumer = _BufferingConsumer() - request_consumer = self._test_method.service( - response_consumer, context, self._control) - - for request in request_iterator: - request_consumer.consume(request) - while response_consumer.consumed: - yield response_consumer.consumed.pop(0) - response_consumer.terminate() - - -class _EventStreamStreamMethod(face_interfaces.MethodImplementation): - - def __init__(self, stream_stream_test_method, control, pool): - self._test_method = stream_stream_test_method - self._control = control - self._pool = pool - - self.cardinality = cardinality.Cardinality.STREAM_STREAM - self.style = style.Service.EVENT - - def stream_stream_event(self, response_consumer, context): - request_consumer = self._test_method.service( - response_consumer, context, self._control) - if self._pool is None: - return request_consumer - else: - return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool) - - -class _UnaryConsumer(stream.Consumer): - """A Consumer that only allows consumption of exactly one value.""" - - def __init__(self, action): - self._lock = threading.Lock() - self._action = action - self._consumed = False - self._terminated = False - - def consume(self, value): - with self._lock: - if self._consumed: - raise ValueError('Unary consumer already consumed!') - elif self._terminated: - raise ValueError('Unary consumer already terminated!') - else: - self._consumed = True - - self._action(value) - - def terminate(self): - with self._lock: - if not self._consumed: - raise ValueError('Unary consumer hasn\'t yet consumed!') - elif self._terminated: - raise ValueError('Unary consumer already terminated!') - else: - self._terminated = True - - def consume_and_terminate(self, value): - with self._lock: - if self._consumed: - raise ValueError('Unary consumer already consumed!') - elif self._terminated: - raise ValueError('Unary consumer already terminated!') - else: - self._consumed = True - self._terminated = True - - self._action(value) - - -class _UnaryUnaryAdaptation(object): - - def __init__(self, unary_unary_test_method): - self._method = unary_unary_test_method - - def service(self, response_consumer, context, control): - def action(request): - self._method.service( - request, response_consumer.consume_and_terminate, context, control) - return _UnaryConsumer(action) - - -class _UnaryStreamAdaptation(object): - - def __init__(self, unary_stream_test_method): - self._method = unary_stream_test_method - - def service(self, response_consumer, context, control): - def action(request): - self._method.service(request, response_consumer, context, control) - return _UnaryConsumer(action) - - -class _StreamUnaryAdaptation(object): - - def __init__(self, stream_unary_test_method): - self._method = stream_unary_test_method - - def service(self, response_consumer, context, control): - return self._method.service( - response_consumer.consume_and_terminate, context, control) - - -class _MultiMethodImplementation(face_interfaces.MultiMethodImplementation): - - def __init__(self, methods, control, pool): - self._methods = methods - self._control = control - self._pool = pool - - def service(self, name, response_consumer, context): - method = self._methods.get(name, None) - if method is None: - raise exceptions.NoSuchMethodError(name) - elif self._pool is None: - return method(response_consumer, context, self._control) - else: - request_consumer = method(response_consumer, context, self._control) - return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool) - - -class _Assembly( - collections.namedtuple( - '_Assembly', - ['methods', 'inlines', 'events', 'adaptations', 'messages'])): - """An intermediate structure created when creating a TestServiceDigest.""" - - -def _assemble( - scenarios, names, inline_method_constructor, event_method_constructor, - adapter, control, pool): - """Creates an _Assembly from the given scenarios.""" - methods = [] - inlines = {} - events = {} - adaptations = {} - messages = {} - for name, scenario in six.iteritems(scenarios): - if name in names: - raise ValueError('Repeated name "%s"!' % name) - - test_method = scenario[0] - inline_method = inline_method_constructor(test_method, control) - event_method = event_method_constructor(test_method, control, pool) - adaptation = adapter(test_method) - - methods.append(test_method) - inlines[name] = inline_method - events[name] = event_method - adaptations[name] = adaptation - messages[name] = scenario[1] - - return _Assembly(methods, inlines, events, adaptations, messages) - - -def digest(service, control, pool): - """Creates a TestServiceDigest from a TestService. - - Args: - service: A testing_service.TestService. - control: A testing_control.Control. - pool: If RPC methods should be serviced in a separate thread, a thread pool. - None if RPC methods should be serviced in the thread belonging to the - run-time that calls for their service. - - Returns: - A TestServiceDigest synthesized from the given service.TestService. - """ - names = set() - - unary_unary = _assemble( - service.unary_unary_scenarios(), names, _InlineUnaryUnaryMethod, - _EventUnaryUnaryMethod, _UnaryUnaryAdaptation, control, pool) - names.update(set(unary_unary.inlines)) - - unary_stream = _assemble( - service.unary_stream_scenarios(), names, _InlineUnaryStreamMethod, - _EventUnaryStreamMethod, _UnaryStreamAdaptation, control, pool) - names.update(set(unary_stream.inlines)) - - stream_unary = _assemble( - service.stream_unary_scenarios(), names, _InlineStreamUnaryMethod, - _EventStreamUnaryMethod, _StreamUnaryAdaptation, control, pool) - names.update(set(stream_unary.inlines)) - - stream_stream = _assemble( - service.stream_stream_scenarios(), names, _InlineStreamStreamMethod, - _EventStreamStreamMethod, _IDENTITY, control, pool) - names.update(set(stream_stream.inlines)) - - methods = list(unary_unary.methods) - methods.extend(unary_stream.methods) - methods.extend(stream_unary.methods) - methods.extend(stream_stream.methods) - adaptations = dict(unary_unary.adaptations) - adaptations.update(unary_stream.adaptations) - adaptations.update(stream_unary.adaptations) - adaptations.update(stream_stream.adaptations) - inlines = dict(unary_unary.inlines) - inlines.update(unary_stream.inlines) - inlines.update(stream_unary.inlines) - inlines.update(stream_stream.inlines) - events = dict(unary_unary.events) - events.update(unary_stream.events) - events.update(stream_unary.events) - events.update(stream_stream.events) - - return TestServiceDigest( - service.name(), - methods, - inlines, - events, - _MultiMethodImplementation(adaptations, control, pool), - unary_unary.messages, - unary_stream.messages, - stream_unary.messages, - stream_stream.messages) diff --git a/src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py deleted file mode 100644 index 98b61e492c..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/event_invocation_synchronous_event_service_test_case.py +++ /dev/null @@ -1,378 +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. - -"""A test to verify an implementation of the Face layer of RPC Framework.""" - -import abc -import unittest - -import six - -from grpc.framework.face import interfaces -from tests.unit.framework.common import test_constants -from tests.unit.framework.face.testing import callback as testing_callback -from tests.unit.framework.face.testing import control -from tests.unit.framework.face.testing import coverage -from tests.unit.framework.face.testing import digest -from tests.unit.framework.face.testing import stock_service -from tests.unit.framework.face.testing import test_case - - -class EventInvocationSynchronousEventServiceTestCase( - six.with_metaclass(abc.ABCMeta, - test_case.FaceTestCase, coverage.FullCoverage)): - """A test of the Face layer of RPC Framework. - - Concrete subclasses must also extend unittest.TestCase. - """ - - def setUp(self): - """See unittest.TestCase.setUp for full specification. - - Overriding implementations must call this implementation. - """ - self.control = control.PauseFailControl() - self.digest = digest.digest( - stock_service.STOCK_TEST_SERVICE, self.control, None) - - self.stub, self.memo = self.set_up_implementation( - self.digest.name, self.digest.methods, - self.digest.event_method_implementations, None) - - def tearDown(self): - """See unittest.TestCase.tearDown for full specification. - - Overriding implementations must call this implementation. - """ - self.tear_down_implementation(self.memo) - - def testSuccessfulUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = testing_callback.Callback() - - self.stub.event_value_in_value_out( - name, request, callback.complete, callback.abort, - test_constants.SHORT_TIMEOUT) - callback.block_until_terminated() - response = callback.response() - - test_messages.verify(request, response, self) - - def testSuccessfulUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = testing_callback.Callback() - - self.stub.event_value_in_stream_out( - name, request, callback, callback.abort, - test_constants.SHORT_TIMEOUT) - callback.block_until_terminated() - responses = callback.responses() - - test_messages.verify(request, responses, self) - - def testSuccessfulStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - callback = testing_callback.Callback() - - unused_call, request_consumer = self.stub.event_stream_in_value_out( - name, callback.complete, callback.abort, - test_constants.SHORT_TIMEOUT) - for request in requests: - request_consumer.consume(request) - request_consumer.terminate() - callback.block_until_terminated() - response = callback.response() - - test_messages.verify(requests, response, self) - - def testSuccessfulStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - callback = testing_callback.Callback() - - unused_call, request_consumer = self.stub.event_stream_in_stream_out( - name, callback, callback.abort, test_constants.SHORT_TIMEOUT) - for request in requests: - request_consumer.consume(request) - request_consumer.terminate() - callback.block_until_terminated() - responses = callback.responses() - - test_messages.verify(requests, responses, self) - - def testSequentialInvocations(self): - # pylint: disable=cell-var-from-loop - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - first_request = test_messages.request() - second_request = test_messages.request() - first_callback = testing_callback.Callback() - second_callback = testing_callback.Callback() - - def make_second_invocation(first_response): - first_callback.complete(first_response) - self.stub.event_value_in_value_out( - name, second_request, second_callback.complete, - second_callback.abort, test_constants.SHORT_TIMEOUT) - - self.stub.event_value_in_value_out( - name, first_request, make_second_invocation, first_callback.abort, - test_constants.SHORT_TIMEOUT) - second_callback.block_until_terminated() - - first_response = first_callback.response() - second_response = second_callback.response() - test_messages.verify(first_request, first_response, self) - test_messages.verify(second_request, second_response, self) - - def testExpiredUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = testing_callback.Callback() - - with self.control.pause(): - self.stub.event_value_in_value_out( - name, request, callback.complete, callback.abort, - test_constants.SHORT_TIMEOUT) - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.EXPIRED, callback.abortion()) - - def testExpiredUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = testing_callback.Callback() - - with self.control.pause(): - self.stub.event_value_in_stream_out( - name, request, callback, callback.abort, - test_constants.SHORT_TIMEOUT) - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.EXPIRED, callback.abortion()) - - def testExpiredStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for unused_test_messages in test_messages_sequence: - callback = testing_callback.Callback() - - self.stub.event_stream_in_value_out( - name, callback.complete, callback.abort, - test_constants.SHORT_TIMEOUT) - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.EXPIRED, callback.abortion()) - - def testExpiredStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - callback = testing_callback.Callback() - - unused_call, request_consumer = self.stub.event_stream_in_stream_out( - name, callback, callback.abort, test_constants.SHORT_TIMEOUT) - for request in requests: - request_consumer.consume(request) - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.EXPIRED, callback.abortion()) - - def testFailedUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = testing_callback.Callback() - - with self.control.fail(): - self.stub.event_value_in_value_out( - name, request, callback.complete, callback.abort, - test_constants.SHORT_TIMEOUT) - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.SERVICER_FAILURE, - callback.abortion()) - - def testFailedUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = testing_callback.Callback() - - with self.control.fail(): - self.stub.event_value_in_stream_out( - name, request, callback, callback.abort, - test_constants.SHORT_TIMEOUT) - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.SERVICER_FAILURE, - callback.abortion()) - - def testFailedStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - callback = testing_callback.Callback() - - with self.control.fail(): - unused_call, request_consumer = self.stub.event_stream_in_value_out( - name, callback.complete, callback.abort, - test_constants.SHORT_TIMEOUT) - for request in requests: - request_consumer.consume(request) - request_consumer.terminate() - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.SERVICER_FAILURE, - callback.abortion()) - - def testFailedStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - callback = testing_callback.Callback() - - with self.control.fail(): - unused_call, request_consumer = self.stub.event_stream_in_stream_out( - name, callback, callback.abort, test_constants.SHORT_TIMEOUT) - for request in requests: - request_consumer.consume(request) - request_consumer.terminate() - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.SERVICER_FAILURE, callback.abortion()) - - def testParallelInvocations(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - first_request = test_messages.request() - first_callback = testing_callback.Callback() - second_request = test_messages.request() - second_callback = testing_callback.Callback() - - self.stub.event_value_in_value_out( - name, first_request, first_callback.complete, first_callback.abort, - test_constants.SHORT_TIMEOUT) - self.stub.event_value_in_value_out( - name, second_request, second_callback.complete, - second_callback.abort, test_constants.SHORT_TIMEOUT) - first_callback.block_until_terminated() - second_callback.block_until_terminated() - - first_response = first_callback.response() - second_response = second_callback.response() - test_messages.verify(first_request, first_response, self) - test_messages.verify(second_request, second_response, self) - - @unittest.skip('TODO(nathaniel): implement.') - def testWaitingForSomeButNotAllParallelInvocations(self): - raise NotImplementedError() - - def testCancelledUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = testing_callback.Callback() - - with self.control.pause(): - call = self.stub.event_value_in_value_out( - name, request, callback.complete, callback.abort, - test_constants.SHORT_TIMEOUT) - call.cancel() - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.CANCELLED, callback.abortion()) - - def testCancelledUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = testing_callback.Callback() - - call = self.stub.event_value_in_stream_out( - name, request, callback, callback.abort, - test_constants.SHORT_TIMEOUT) - call.cancel() - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.CANCELLED, callback.abortion()) - - def testCancelledStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - callback = testing_callback.Callback() - - call, request_consumer = self.stub.event_stream_in_value_out( - name, callback.complete, callback.abort, - test_constants.SHORT_TIMEOUT) - for request in requests: - request_consumer.consume(request) - call.cancel() - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.CANCELLED, callback.abortion()) - - def testCancelledStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for unused_test_messages in test_messages_sequence: - callback = testing_callback.Callback() - - call, unused_request_consumer = self.stub.event_stream_in_stream_out( - name, callback, callback.abort, test_constants.SHORT_TIMEOUT) - call.cancel() - callback.block_until_terminated() - - self.assertEqual(interfaces.Abortion.CANCELLED, callback.abortion()) diff --git a/src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py deleted file mode 100644 index cae791af97..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py +++ /dev/null @@ -1,384 +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. - -"""A test to verify an implementation of the Face layer of RPC Framework.""" - -import abc -import contextlib -import threading -import unittest - -import six - -from grpc.framework.face import exceptions -from grpc.framework.foundation import future -from grpc.framework.foundation import logging_pool -from tests.unit.framework.common import test_constants -from tests.unit.framework.face.testing import control -from tests.unit.framework.face.testing import coverage -from tests.unit.framework.face.testing import digest -from tests.unit.framework.face.testing import stock_service -from tests.unit.framework.face.testing import test_case - -_MAXIMUM_POOL_SIZE = 10 - - -class _PauseableIterator(object): - - def __init__(self, upstream): - self._upstream = upstream - self._condition = threading.Condition() - self._paused = False - - @contextlib.contextmanager - def pause(self): - with self._condition: - self._paused = True - yield - with self._condition: - self._paused = False - self._condition.notify_all() - - def __iter__(self): - return self - - def __next__(self): - return self.next() - - def next(self): - with self._condition: - while self._paused: - self._condition.wait() - return next(self._upstream) - - -class FutureInvocationAsynchronousEventServiceTestCase( - six.with_metaclass(abc.ABCMeta, - test_case.FaceTestCase, coverage.FullCoverage)): - """A test of the Face layer of RPC Framework. - - Concrete subclasses must also extend unittest.TestCase. - """ - - def setUp(self): - """See unittest.TestCase.setUp for full specification. - - Overriding implementations must call this implementation. - """ - self.control = control.PauseFailControl() - self.digest_pool = logging_pool.pool(_MAXIMUM_POOL_SIZE) - self.digest = digest.digest( - stock_service.STOCK_TEST_SERVICE, self.control, self.digest_pool) - - self.stub, self.memo = self.set_up_implementation( - self.digest.name, self.digest.methods, - self.digest.event_method_implementations, None) - - def tearDown(self): - """See unittest.TestCase.tearDown for full specification. - - Overriding implementations must call this implementation. - """ - self.tear_down_implementation(self.memo) - self.digest_pool.shutdown(wait=True) - - def testSuccessfulUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - response_future = self.stub.future_value_in_value_out( - name, request, test_constants.SHORT_TIMEOUT) - response = response_future.result() - - test_messages.verify(request, response, self) - - def testSuccessfulUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - response_iterator = self.stub.inline_value_in_stream_out( - name, request, test_constants.SHORT_TIMEOUT) - responses = list(response_iterator) - - test_messages.verify(request, responses, self) - - def testSuccessfulStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - request_iterator = _PauseableIterator(iter(requests)) - - # Use of a paused iterator of requests allows us to test that control is - # returned to calling code before the iterator yields any requests. - with request_iterator.pause(): - response_future = self.stub.future_stream_in_value_out( - name, request_iterator, test_constants.SHORT_TIMEOUT) - response = response_future.result() - - test_messages.verify(requests, response, self) - - def testSuccessfulStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - request_iterator = _PauseableIterator(iter(requests)) - - # Use of a paused iterator of requests allows us to test that control is - # returned to calling code before the iterator yields any requests. - with request_iterator.pause(): - response_iterator = self.stub.inline_stream_in_stream_out( - name, request_iterator, test_constants.SHORT_TIMEOUT) - responses = list(response_iterator) - - test_messages.verify(requests, responses, self) - - def testSequentialInvocations(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - first_request = test_messages.request() - second_request = test_messages.request() - - first_response_future = self.stub.future_value_in_value_out( - name, first_request, test_constants.SHORT_TIMEOUT) - first_response = first_response_future.result() - - test_messages.verify(first_request, first_response, self) - - second_response_future = self.stub.future_value_in_value_out( - name, second_request, test_constants.SHORT_TIMEOUT) - second_response = second_response_future.result() - - test_messages.verify(second_request, second_response, self) - - def testExpiredUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self.control.pause(): - multi_callable = self.stub.unary_unary_multi_callable(name) - response_future = multi_callable.future(request, - test_constants.SHORT_TIMEOUT) - self.assertIsInstance( - response_future.exception(), exceptions.ExpirationError) - with self.assertRaises(exceptions.ExpirationError): - response_future.result() - - def testExpiredUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self.control.pause(): - response_iterator = self.stub.inline_value_in_stream_out( - name, request, test_constants.SHORT_TIMEOUT) - with self.assertRaises(exceptions.ExpirationError): - list(response_iterator) - - def testExpiredStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self.control.pause(): - multi_callable = self.stub.stream_unary_multi_callable(name) - response_future = multi_callable.future(iter(requests), - test_constants.SHORT_TIMEOUT) - self.assertIsInstance( - response_future.exception(), exceptions.ExpirationError) - with self.assertRaises(exceptions.ExpirationError): - response_future.result() - - def testExpiredStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self.control.pause(): - response_iterator = self.stub.inline_stream_in_stream_out( - name, iter(requests), test_constants.SHORT_TIMEOUT) - with self.assertRaises(exceptions.ExpirationError): - list(response_iterator) - - def testFailedUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self.control.fail(): - response_future = self.stub.future_value_in_value_out( - name, request, test_constants.SHORT_TIMEOUT) - - # Because the servicer fails outside of the thread from which the - # servicer-side runtime called into it its failure is - # indistinguishable from simply not having called its - # response_callback before the expiration of the RPC. - self.assertIsInstance( - response_future.exception(), exceptions.ExpirationError) - with self.assertRaises(exceptions.ExpirationError): - response_future.result() - - def testFailedUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - # Because the servicer fails outside of the thread from which the - # servicer-side runtime called into it its failure is indistinguishable - # from simply not having called its response_consumer before the - # expiration of the RPC. - with self.control.fail(), self.assertRaises(exceptions.ExpirationError): - response_iterator = self.stub.inline_value_in_stream_out( - name, request, test_constants.SHORT_TIMEOUT) - list(response_iterator) - - def testFailedStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self.control.fail(): - response_future = self.stub.future_stream_in_value_out( - name, iter(requests), test_constants.SHORT_TIMEOUT) - - # Because the servicer fails outside of the thread from which the - # servicer-side runtime called into it its failure is - # indistinguishable from simply not having called its - # response_callback before the expiration of the RPC. - self.assertIsInstance( - response_future.exception(), exceptions.ExpirationError) - with self.assertRaises(exceptions.ExpirationError): - response_future.result() - - def testFailedStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - # Because the servicer fails outside of the thread from which the - # servicer-side runtime called into it its failure is indistinguishable - # from simply not having called its response_consumer before the - # expiration of the RPC. - with self.control.fail(), self.assertRaises(exceptions.ExpirationError): - response_iterator = self.stub.inline_stream_in_stream_out( - name, iter(requests), test_constants.SHORT_TIMEOUT) - list(response_iterator) - - def testParallelInvocations(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - first_request = test_messages.request() - second_request = test_messages.request() - - # TODO(bug 2039): use LONG_TIMEOUT instead - first_response_future = self.stub.future_value_in_value_out( - name, first_request, test_constants.SHORT_TIMEOUT) - second_response_future = self.stub.future_value_in_value_out( - name, second_request, test_constants.SHORT_TIMEOUT) - first_response = first_response_future.result() - second_response = second_response_future.result() - - test_messages.verify(first_request, first_response, self) - test_messages.verify(second_request, second_response, self) - - @unittest.skip('TODO(nathaniel): implement.') - def testWaitingForSomeButNotAllParallelInvocations(self): - raise NotImplementedError() - - def testCancelledUnaryRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self.control.pause(): - response_future = self.stub.future_value_in_value_out( - name, request, test_constants.SHORT_TIMEOUT) - cancel_method_return_value = response_future.cancel() - - self.assertFalse(cancel_method_return_value) - self.assertTrue(response_future.cancelled()) - - def testCancelledUnaryRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self.control.pause(): - response_iterator = self.stub.inline_value_in_stream_out( - name, request, test_constants.SHORT_TIMEOUT) - response_iterator.cancel() - - with self.assertRaises(future.CancelledError): - next(response_iterator) - - def testCancelledStreamRequestUnaryResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self.control.pause(): - response_future = self.stub.future_stream_in_value_out( - name, iter(requests), test_constants.SHORT_TIMEOUT) - cancel_method_return_value = response_future.cancel() - - self.assertFalse(cancel_method_return_value) - self.assertTrue(response_future.cancelled()) - - def testCancelledStreamRequestStreamResponse(self): - for name, test_messages_sequence in ( - six.iteritems(self.digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self.control.pause(): - response_iterator = self.stub.inline_stream_in_stream_out( - name, iter(requests), test_constants.SHORT_TIMEOUT) - response_iterator.cancel() - - with self.assertRaises(future.CancelledError): - next(response_iterator) diff --git a/src/python/grpcio/tests/unit/framework/face/testing/interfaces.py b/src/python/grpcio/tests/unit/framework/face/testing/interfaces.py deleted file mode 100644 index 8a25f89c88..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/interfaces.py +++ /dev/null @@ -1,118 +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. - -"""Interfaces implemented by data sets used in Face-layer tests.""" - -import abc - -import six - -# cardinality is referenced from specification in this module. -from grpc.framework.common import cardinality # pylint: disable=unused-import - - -class Method(six.with_metaclass(abc.ABCMeta)): - """An RPC method to be used in tests of RPC implementations.""" - - @abc.abstractmethod - def name(self): - """Identify the name of the method. - - Returns: - The name of the method. - """ - raise NotImplementedError() - - @abc.abstractmethod - def cardinality(self): - """Identify the cardinality of the method. - - Returns: - A cardinality.Cardinality value describing the streaming semantics of the - method. - """ - raise NotImplementedError() - - @abc.abstractmethod - def request_class(self): - """Identify the class used for the method's request objects. - - Returns: - The class object of the class to which the method's request objects - belong. - """ - raise NotImplementedError() - - @abc.abstractmethod - def response_class(self): - """Identify the class used for the method's response objects. - - Returns: - The class object of the class to which the method's response objects - belong. - """ - raise NotImplementedError() - - @abc.abstractmethod - def serialize_request(self, request): - """Serialize the given request object. - - Args: - request: A request object appropriate for this method. - """ - raise NotImplementedError() - - @abc.abstractmethod - def deserialize_request(self, serialized_request): - """Synthesize a request object from a given bytestring. - - Args: - serialized_request: A bytestring deserializable into a request object - appropriate for this method. - """ - raise NotImplementedError() - - @abc.abstractmethod - def serialize_response(self, response): - """Serialize the given response object. - - Args: - response: A response object appropriate for this method. - """ - raise NotImplementedError() - - @abc.abstractmethod - def deserialize_response(self, serialized_response): - """Synthesize a response object from a given bytestring. - - Args: - serialized_response: A bytestring deserializable into a response object - appropriate for this method. - """ - raise NotImplementedError() diff --git a/src/python/grpcio/tests/unit/framework/face/testing/service.py b/src/python/grpcio/tests/unit/framework/face/testing/service.py deleted file mode 100644 index 3e4228cc07..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/service.py +++ /dev/null @@ -1,321 +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. - -"""Private interfaces implemented by data sets used in Face-layer tests.""" - -import abc - -import six - -# interfaces is referenced from specification in this module. -from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import -from tests.unit.framework.face.testing import interfaces - - -class UnaryUnaryTestMethodImplementation(six.with_metaclass(abc.ABCMeta, interfaces.Method)): - """A controllable implementation of a unary-unary RPC method.""" - - @abc.abstractmethod - def service(self, request, response_callback, context, control): - """Services an RPC that accepts one message and produces one message. - - Args: - request: The single request message for the RPC. - response_callback: A callback to be called to accept the response message - of the RPC. - context: An face_interfaces.RpcContext object. - control: A test_control.Control to control execution of this method. - - Raises: - abandonment.Abandoned: May or may not be raised when the RPC has been - aborted. - """ - raise NotImplementedError() - - -class UnaryUnaryTestMessages(six.with_metaclass(abc.ABCMeta)): - """A type for unary-request-unary-response message pairings.""" - - @abc.abstractmethod - def request(self): - """Affords a request message. - - Implementations of this method should return a different message with each - call so that multiple test executions of the test method may be made with - different inputs. - - Returns: - A request message. - """ - raise NotImplementedError() - - @abc.abstractmethod - def verify(self, request, response, test_case): - """Verifies that the computed response matches the given request. - - Args: - request: A request message. - response: A response message. - test_case: A unittest.TestCase object affording useful assertion methods. - - Raises: - AssertionError: If the request and response do not match, indicating that - there was some problem executing the RPC under test. - """ - raise NotImplementedError() - - -class UnaryStreamTestMethodImplementation(six.with_metaclass(abc.ABCMeta, interfaces.Method)): - """A controllable implementation of a unary-stream RPC method.""" - - @abc.abstractmethod - def service(self, request, response_consumer, context, control): - """Services an RPC that takes one message and produces a stream of messages. - - Args: - request: The single request message for the RPC. - response_consumer: A stream.Consumer to be called to accept the response - messages of the RPC. - context: A face_interfaces.RpcContext object. - control: A test_control.Control to control execution of this method. - - Raises: - abandonment.Abandoned: May or may not be raised when the RPC has been - aborted. - """ - raise NotImplementedError() - - -class UnaryStreamTestMessages(six.with_metaclass(abc.ABCMeta)): - """A type for unary-request-stream-response message pairings.""" - - @abc.abstractmethod - def request(self): - """Affords a request message. - - Implementations of this method should return a different message with each - call so that multiple test executions of the test method may be made with - different inputs. - - Returns: - A request message. - """ - raise NotImplementedError() - - @abc.abstractmethod - def verify(self, request, responses, test_case): - """Verifies that the computed responses match the given request. - - Args: - request: A request message. - responses: A sequence of response messages. - test_case: A unittest.TestCase object affording useful assertion methods. - - Raises: - AssertionError: If the request and responses do not match, indicating that - there was some problem executing the RPC under test. - """ - raise NotImplementedError() - - -class StreamUnaryTestMethodImplementation(six.with_metaclass(abc.ABCMeta, interfaces.Method)): - """A controllable implementation of a stream-unary RPC method.""" - - @abc.abstractmethod - def service(self, response_callback, context, control): - """Services an RPC that takes a stream of messages and produces one message. - - Args: - response_callback: A callback to be called to accept the response message - of the RPC. - context: A face_interfaces.RpcContext object. - control: A test_control.Control to control execution of this method. - - Returns: - A stream.Consumer with which to accept the request messages of the RPC. - The consumer returned from this method may or may not be invoked to - completion: in the case of RPC abortion, RPC Framework will simply stop - passing messages to this object. Implementations must not assume that - this object will be called to completion of the request stream or even - called at all. - - Raises: - abandonment.Abandoned: May or may not be raised when the RPC has been - aborted. - """ - raise NotImplementedError() - - -class StreamUnaryTestMessages(six.with_metaclass(abc.ABCMeta)): - """A type for stream-request-unary-response message pairings.""" - - @abc.abstractmethod - def requests(self): - """Affords a sequence of request messages. - - Implementations of this method should return a different sequences with each - call so that multiple test executions of the test method may be made with - different inputs. - - Returns: - A sequence of request messages. - """ - raise NotImplementedError() - - @abc.abstractmethod - def verify(self, requests, response, test_case): - """Verifies that the computed response matches the given requests. - - Args: - requests: A sequence of request messages. - response: A response message. - test_case: A unittest.TestCase object affording useful assertion methods. - - Raises: - AssertionError: If the requests and response do not match, indicating that - there was some problem executing the RPC under test. - """ - raise NotImplementedError() - - -class StreamStreamTestMethodImplementation(six.with_metaclass(abc.ABCMeta, interfaces.Method)): - """A controllable implementation of a stream-stream RPC method.""" - - @abc.abstractmethod - def service(self, response_consumer, context, control): - """Services an RPC that accepts and produces streams of messages. - - Args: - response_consumer: A stream.Consumer to be called to accept the response - messages of the RPC. - context: A face_interfaces.RpcContext object. - control: A test_control.Control to control execution of this method. - - Returns: - A stream.Consumer with which to accept the request messages of the RPC. - The consumer returned from this method may or may not be invoked to - completion: in the case of RPC abortion, RPC Framework will simply stop - passing messages to this object. Implementations must not assume that - this object will be called to completion of the request stream or even - called at all. - - Raises: - abandonment.Abandoned: May or may not be raised when the RPC has been - aborted. - """ - raise NotImplementedError() - - -class StreamStreamTestMessages(six.with_metaclass(abc.ABCMeta)): - """A type for stream-request-stream-response message pairings.""" - - @abc.abstractmethod - def requests(self): - """Affords a sequence of request messages. - - Implementations of this method should return a different sequences with each - call so that multiple test executions of the test method may be made with - different inputs. - - Returns: - A sequence of request messages. - """ - raise NotImplementedError() - - @abc.abstractmethod - def verify(self, requests, responses, test_case): - """Verifies that the computed response matches the given requests. - - Args: - requests: A sequence of request messages. - responses: A sequence of response messages. - test_case: A unittest.TestCase object affording useful assertion methods. - - Raises: - AssertionError: If the requests and responses do not match, indicating - that there was some problem executing the RPC under test. - """ - raise NotImplementedError() - - -class TestService(six.with_metaclass(abc.ABCMeta)): - """A specification of implemented RPC methods to use in tests.""" - - @abc.abstractmethod - def name(self): - """Identifies the RPC service name used during the test. - - Returns: - The RPC service name to be used for the test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def unary_unary_scenarios(self): - """Affords unary-request-unary-response test methods and their messages. - - Returns: - A dict from method name to pair. The first element of the pair - is a UnaryUnaryTestMethodImplementation object and the second element - is a sequence of UnaryUnaryTestMethodMessages objects. - """ - raise NotImplementedError() - - @abc.abstractmethod - def unary_stream_scenarios(self): - """Affords unary-request-stream-response test methods and their messages. - - Returns: - A dict from method name to pair. The first element of the pair is a - UnaryStreamTestMethodImplementation object and the second element is a - sequence of UnaryStreamTestMethodMessages objects. - """ - raise NotImplementedError() - - @abc.abstractmethod - def stream_unary_scenarios(self): - """Affords stream-request-unary-response test methods and their messages. - - Returns: - A dict from method name to pair. The first element of the pair is a - StreamUnaryTestMethodImplementation object and the second element is a - sequence of StreamUnaryTestMethodMessages objects. - """ - raise NotImplementedError() - - @abc.abstractmethod - def stream_stream_scenarios(self): - """Affords stream-request-stream-response test methods and their messages. - - Returns: - A dict from method name to pair. The first element of the pair is a - StreamStreamTestMethodImplementation object and the second element is a - sequence of StreamStreamTestMethodMessages objects. - """ - raise NotImplementedError() diff --git a/src/python/grpcio/tests/unit/framework/face/testing/stock_service.py b/src/python/grpcio/tests/unit/framework/face/testing/stock_service.py deleted file mode 100644 index 117c723f79..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/stock_service.py +++ /dev/null @@ -1,374 +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. - -"""Examples of Python implementations of the stock.proto Stock service.""" - -from grpc.framework.common import cardinality -from grpc.framework.foundation import abandonment -from grpc.framework.foundation import stream -from grpc.framework.foundation import stream_util -from tests.unit.framework.face.testing import service -from tests.unit._junkdrawer import stock_pb2 - -SYMBOL_FORMAT = 'test symbol:%03d' -STREAM_LENGTH = 400 - -# A test-appropriate security-pricing function. :-P -_price = lambda symbol_name: float(hash(symbol_name) % 4096) - - -def _get_last_trade_price(stock_request, stock_reply_callback, control, active): - """A unary-request, unary-response test method.""" - control.control() - if active(): - stock_reply_callback( - stock_pb2.StockReply( - symbol=stock_request.symbol, price=_price(stock_request.symbol))) - else: - raise abandonment.Abandoned() - - -def _get_last_trade_price_multiple(stock_reply_consumer, control, active): - """A stream-request, stream-response test method.""" - def stock_reply_for_stock_request(stock_request): - control.control() - if active(): - return stock_pb2.StockReply( - symbol=stock_request.symbol, price=_price(stock_request.symbol)) - else: - raise abandonment.Abandoned() - return stream_util.TransformingConsumer( - stock_reply_for_stock_request, stock_reply_consumer) - - -def _watch_future_trades(stock_request, stock_reply_consumer, control, active): - """A unary-request, stream-response test method.""" - base_price = _price(stock_request.symbol) - for index in range(stock_request.num_trades_to_watch): - control.control() - if active(): - stock_reply_consumer.consume( - stock_pb2.StockReply( - symbol=stock_request.symbol, price=base_price + index)) - else: - raise abandonment.Abandoned() - stock_reply_consumer.terminate() - - -def _get_highest_trade_price(stock_reply_callback, control, active): - """A stream-request, unary-response test method.""" - - class StockRequestConsumer(stream.Consumer): - """Keeps an ongoing record of the most valuable symbol yet consumed.""" - - def __init__(self): - self._symbol = None - self._price = None - - def consume(self, stock_request): - control.control() - if active(): - if self._price is None: - self._symbol = stock_request.symbol - self._price = _price(stock_request.symbol) - else: - candidate_price = _price(stock_request.symbol) - if self._price < candidate_price: - self._symbol = stock_request.symbol - self._price = candidate_price - - def terminate(self): - control.control() - if active(): - if self._symbol is None: - raise ValueError() - else: - stock_reply_callback( - stock_pb2.StockReply(symbol=self._symbol, price=self._price)) - self._symbol = None - self._price = None - - def consume_and_terminate(self, stock_request): - control.control() - if active(): - if self._price is None: - stock_reply_callback( - stock_pb2.StockReply( - symbol=stock_request.symbol, - price=_price(stock_request.symbol))) - else: - candidate_price = _price(stock_request.symbol) - if self._price < candidate_price: - stock_reply_callback( - stock_pb2.StockReply( - symbol=stock_request.symbol, price=candidate_price)) - else: - stock_reply_callback( - stock_pb2.StockReply( - symbol=self._symbol, price=self._price)) - - self._symbol = None - self._price = None - - return StockRequestConsumer() - - -class GetLastTradePrice(service.UnaryUnaryTestMethodImplementation): - """GetLastTradePrice for use in tests.""" - - def name(self): - return 'GetLastTradePrice' - - def cardinality(self): - return cardinality.Cardinality.UNARY_UNARY - - def request_class(self): - return stock_pb2.StockRequest - - def response_class(self): - return stock_pb2.StockReply - - def serialize_request(self, request): - return request.SerializeToString() - - def deserialize_request(self, serialized_request): - return stock_pb2.StockRequest.FromString(serialized_request) - - def serialize_response(self, response): - return response.SerializeToString() - - def deserialize_response(self, serialized_response): - return stock_pb2.StockReply.FromString(serialized_response) - - def service(self, request, response_callback, context, control): - _get_last_trade_price( - request, response_callback, control, context.is_active) - - -class GetLastTradePriceMessages(service.UnaryUnaryTestMessages): - - def __init__(self): - self._index = 0 - - def request(self): - symbol = SYMBOL_FORMAT % self._index - self._index += 1 - return stock_pb2.StockRequest(symbol=symbol) - - def verify(self, request, response, test_case): - test_case.assertEqual(request.symbol, response.symbol) - test_case.assertEqual(_price(request.symbol), response.price) - - -class GetLastTradePriceMultiple(service.StreamStreamTestMethodImplementation): - """GetLastTradePriceMultiple for use in tests.""" - - def name(self): - return 'GetLastTradePriceMultiple' - - def cardinality(self): - return cardinality.Cardinality.STREAM_STREAM - - def request_class(self): - return stock_pb2.StockRequest - - def response_class(self): - return stock_pb2.StockReply - - def serialize_request(self, request): - return request.SerializeToString() - - def deserialize_request(self, serialized_request): - return stock_pb2.StockRequest.FromString(serialized_request) - - def serialize_response(self, response): - return response.SerializeToString() - - def deserialize_response(self, serialized_response): - return stock_pb2.StockReply.FromString(serialized_response) - - def service(self, response_consumer, context, control): - return _get_last_trade_price_multiple( - response_consumer, control, context.is_active) - - -class GetLastTradePriceMultipleMessages(service.StreamStreamTestMessages): - """Pairs of message streams for use with GetLastTradePriceMultiple.""" - - def __init__(self): - self._index = 0 - - def requests(self): - base_index = self._index - self._index += 1 - return [ - stock_pb2.StockRequest(symbol=SYMBOL_FORMAT % (base_index + index)) - for index in range(STREAM_LENGTH)] - - def verify(self, requests, responses, test_case): - test_case.assertEqual(len(requests), len(responses)) - for stock_request, stock_reply in zip(requests, responses): - test_case.assertEqual(stock_request.symbol, stock_reply.symbol) - test_case.assertEqual(_price(stock_request.symbol), stock_reply.price) - - -class WatchFutureTrades(service.UnaryStreamTestMethodImplementation): - """WatchFutureTrades for use in tests.""" - - def name(self): - return 'WatchFutureTrades' - - def cardinality(self): - return cardinality.Cardinality.UNARY_STREAM - - def request_class(self): - return stock_pb2.StockRequest - - def response_class(self): - return stock_pb2.StockReply - - def serialize_request(self, request): - return request.SerializeToString() - - def deserialize_request(self, serialized_request): - return stock_pb2.StockRequest.FromString(serialized_request) - - def serialize_response(self, response): - return response.SerializeToString() - - def deserialize_response(self, serialized_response): - return stock_pb2.StockReply.FromString(serialized_response) - - def service(self, request, response_consumer, context, control): - _watch_future_trades(request, response_consumer, control, context.is_active) - - -class WatchFutureTradesMessages(service.UnaryStreamTestMessages): - """Pairs of a single request message and a sequence of response messages.""" - - def __init__(self): - self._index = 0 - - def request(self): - symbol = SYMBOL_FORMAT % self._index - self._index += 1 - return stock_pb2.StockRequest( - symbol=symbol, num_trades_to_watch=STREAM_LENGTH) - - def verify(self, request, responses, test_case): - test_case.assertEqual(STREAM_LENGTH, len(responses)) - base_price = _price(request.symbol) - for index, response in enumerate(responses): - test_case.assertEqual(base_price + index, response.price) - - -class GetHighestTradePrice(service.StreamUnaryTestMethodImplementation): - """GetHighestTradePrice for use in tests.""" - - def name(self): - return 'GetHighestTradePrice' - - def cardinality(self): - return cardinality.Cardinality.STREAM_UNARY - - def request_class(self): - return stock_pb2.StockRequest - - def response_class(self): - return stock_pb2.StockReply - - def serialize_request(self, request): - return request.SerializeToString() - - def deserialize_request(self, serialized_request): - return stock_pb2.StockRequest.FromString(serialized_request) - - def serialize_response(self, response): - return response.SerializeToString() - - def deserialize_response(self, serialized_response): - return stock_pb2.StockReply.FromString(serialized_response) - - def service(self, response_callback, context, control): - return _get_highest_trade_price( - response_callback, control, context.is_active) - - -class GetHighestTradePriceMessages(service.StreamUnaryTestMessages): - - def requests(self): - return [ - stock_pb2.StockRequest(symbol=SYMBOL_FORMAT % index) - for index in range(STREAM_LENGTH)] - - def verify(self, requests, response, test_case): - price = None - symbol = None - for stock_request in requests: - current_symbol = stock_request.symbol - current_price = _price(current_symbol) - if price is None or price < current_price: - price = current_price - symbol = current_symbol - test_case.assertEqual(price, response.price) - test_case.assertEqual(symbol, response.symbol) - - -class StockTestService(service.TestService): - """A corpus of test data with one method of each RPC cardinality.""" - - def name(self): - return 'Stock' - - def unary_unary_scenarios(self): - return { - 'GetLastTradePrice': ( - GetLastTradePrice(), [GetLastTradePriceMessages()]), - } - - def unary_stream_scenarios(self): - return { - 'WatchFutureTrades': ( - WatchFutureTrades(), [WatchFutureTradesMessages()]), - } - - def stream_unary_scenarios(self): - return { - 'GetHighestTradePrice': ( - GetHighestTradePrice(), [GetHighestTradePriceMessages()]) - } - - def stream_stream_scenarios(self): - return { - 'GetLastTradePriceMultiple': ( - GetLastTradePriceMultiple(), [GetLastTradePriceMultipleMessages()]), - } - - -STOCK_TEST_SERVICE = StockTestService() diff --git a/src/python/grpcio/tests/unit/framework/face/testing/test_case.py b/src/python/grpcio/tests/unit/framework/face/testing/test_case.py deleted file mode 100644 index f29d400844..0000000000 --- a/src/python/grpcio/tests/unit/framework/face/testing/test_case.py +++ /dev/null @@ -1,81 +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. - -"""Tools for creating tests of implementations of the Face layer.""" - -import abc - -import six - -# face_interfaces and interfaces are referenced in specification in this module. -from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import -from tests.unit.framework.face.testing import interfaces # pylint: disable=unused-import - - -class FaceTestCase(six.with_metaclass(abc.ABCMeta)): - """Describes a test of the Face Layer of RPC Framework. - - Concrete subclasses must also inherit from unittest.TestCase and from at least - one class that defines test methods. - """ - - @abc.abstractmethod - def set_up_implementation( - self, name, methods, method_implementations, - multi_method_implementation): - """Instantiates the Face Layer implementation under test. - - Args: - name: The service name to be used in the test. - methods: A sequence of interfaces.Method objects describing the RPC - methods that will be called during the test. - method_implementations: A dictionary from string RPC method name to - face_interfaces.MethodImplementation object specifying - implementation of an RPC method. - multi_method_implementation: An face_interfaces.MultiMethodImplementation - or None. - - Returns: - A sequence of length two the first element of which is a - face_interfaces.GenericStub (backed by the given method - implementations), and the second element of which is an arbitrary memo - object to be kept and passed to tearDownImplementation at the conclusion - of the test. - """ - raise NotImplementedError() - - @abc.abstractmethod - def tear_down_implementation(self, memo): - """Destroys the Face layer implementation under test. - - Args: - memo: The object from the second position of the return value of - set_up_implementation. - """ - raise NotImplementedError() -- cgit v1.2.3 From 0482c1046b837be17c3a056af6569d84b8f52c23 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Tue, 19 Apr 2016 12:08:34 -0700 Subject: Python QPS Worker/initial scenarios --- src/python/grpcio/tests/qps/__init__.py | 28 ++++ src/python/grpcio/tests/qps/benchmark_client.py | 186 +++++++++++++++++++++++ src/python/grpcio/tests/qps/benchmark_server.py | 58 +++++++ src/python/grpcio/tests/qps/client_runner.py | 104 +++++++++++++ src/python/grpcio/tests/qps/histogram.py | 85 +++++++++++ src/python/grpcio/tests/qps/qps_worker.py | 60 ++++++++ src/python/grpcio/tests/qps/worker_server.py | 184 ++++++++++++++++++++++ tools/gce/linux_performance_worker_init.sh | 2 + tools/jenkins/run_performance.sh | 2 +- tools/run_tests/performance/run_worker_python.sh | 35 +++++ tools/run_tests/performance/scenario_config.py | 123 +++++++++++++++ tools/run_tests/run_performance_tests.py | 6 +- 12 files changed, 869 insertions(+), 4 deletions(-) create mode 100644 src/python/grpcio/tests/qps/__init__.py create mode 100644 src/python/grpcio/tests/qps/benchmark_client.py create mode 100644 src/python/grpcio/tests/qps/benchmark_server.py create mode 100644 src/python/grpcio/tests/qps/client_runner.py create mode 100644 src/python/grpcio/tests/qps/histogram.py create mode 100644 src/python/grpcio/tests/qps/qps_worker.py create mode 100644 src/python/grpcio/tests/qps/worker_server.py create mode 100755 tools/run_tests/performance/run_worker_python.sh (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/tests/qps/__init__.py b/src/python/grpcio/tests/qps/__init__.py new file mode 100644 index 0000000000..100a624dc9 --- /dev/null +++ b/src/python/grpcio/tests/qps/__init__.py @@ -0,0 +1,28 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/python/grpcio/tests/qps/benchmark_client.py b/src/python/grpcio/tests/qps/benchmark_client.py new file mode 100644 index 0000000000..eed0b0c6da --- /dev/null +++ b/src/python/grpcio/tests/qps/benchmark_client.py @@ -0,0 +1,186 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Defines test client behaviors (UNARY/STREAMING) (SYNC/ASYNC).""" + +import abc +import time +try: + import Queue as queue # Python 2.x +except ImportError: + import queue # Python 3 + +from concurrent import futures + +from grpc.beta import implementations +from src.proto.grpc.testing import messages_pb2 +from src.proto.grpc.testing import services_pb2 +from tests.unit import resources +from tests.unit.beta import test_utilities + +_TIMEOUT = 60 * 60 * 24 + + +class BenchmarkClient: + """Benchmark client interface that exposes a non-blocking send_request().""" + + __metaclass__ = abc.ABCMeta + + def __init__(self, server, config, hist): + # Create the stub + host, port = server.split(':') + port = int(port) + if config.HasField('security_params'): + creds = implementations.ssl_channel_credentials( + resources.test_root_certificates()) + channel = test_utilities.not_really_secure_channel( + host, port, creds, config.security_params.server_host_override) + else: + channel = implementations.insecure_channel(host, port) + + if config.payload_config.WhichOneof('payload') == 'simple_params': + self._generic = False + self._stub = services_pb2.beta_create_BenchmarkService_stub(channel) + payload = messages_pb2.Payload( + body='\0' * config.payload_config.simple_params.req_size) + self._request = messages_pb2.SimpleRequest( + payload=payload, + response_size=config.payload_config.simple_params.resp_size) + else: + self._generic = True + self._stub = implementations.generic_stub(channel) + self._request = '\0' * config.payload_config.bytebuf_params.req_size + + self._hist = hist + self._response_callbacks = [] + + def add_response_callback(self, callback): + self._response_callbacks.append(callback) + + @abc.abstractmethod + def send_request(self): + """Non-blocking wrapper for a client's request operation.""" + raise NotImplementedError() + + def start(self): + pass + + def stop(self): + pass + + def _handle_response(self, query_time): + self._hist.add(query_time * 1e9) # Report times in nanoseconds + for callback in self._response_callbacks: + callback(query_time) + + +class UnarySyncBenchmarkClient(BenchmarkClient): + + def __init__(self, server, config, hist): + super(UnarySyncBenchmarkClient, self).__init__(server, config, hist) + self._pool = futures.ThreadPoolExecutor( + max_workers=config.outstanding_rpcs_per_channel) + + def send_request(self): + # Send requests in seperate threads to support multiple outstanding rpcs + # (See src/proto/grpc/testing/control.proto) + self._pool.submit(self._dispatch_request) + + def stop(self): + self._pool.shutdown(wait=True) + self._stub = None + + def _dispatch_request(self): + start_time = time.time() + self._stub.UnaryCall(self._request, _TIMEOUT) + end_time = time.time() + self._handle_response(end_time - start_time) + + +class UnaryAsyncBenchmarkClient(BenchmarkClient): + + def send_request(self): + # Use the Future callback api to support multiple outstanding rpcs + start_time = time.time() + response_future = self._stub.UnaryCall.future(self._request, _TIMEOUT) + response_future.add_done_callback( + lambda resp: self._response_received(start_time, resp)) + + def _response_received(self, start_time, resp): + resp.result() + end_time = time.time() + self._handle_response(end_time - start_time) + + def stop(self): + self._stub = None + + +class StreamingAsyncBenchmarkClient(BenchmarkClient): + + def __init__(self, server, config, hist): + super(StreamingAsyncBenchmarkClient, self).__init__(server, config, hist) + self._is_streaming = False + self._pool = futures.ThreadPoolExecutor(max_workers=1) + # Use a thread-safe queue to put requests on the stream + self._request_queue = queue.Queue() + self._send_time_queue = queue.Queue() + + def send_request(self): + self._send_time_queue.put(time.time()) + self._request_queue.put(self._request) + + def start(self): + self._is_streaming = True + self._pool.submit(self._request_stream) + + def stop(self): + self._is_streaming = False + self._pool.shutdown(wait=True) + self._stub = None + + def _request_stream(self): + self._is_streaming = True + if self._generic: + response_stream = self._stub.inline_stream_stream( + 'grpc.testing.BenchmarkService', 'StreamingCall', + self._request_generator(), _TIMEOUT) + else: + response_stream = self._stub.StreamingCall(self._request_generator(), + _TIMEOUT) + for _ in response_stream: + end_time = time.time() + self._handle_response(end_time - self._send_time_queue.get_nowait()) + + def _request_generator(self): + while self._is_streaming: + try: + request = self._request_queue.get(block=True, timeout=1.0) + yield request + except queue.Empty: + pass diff --git a/src/python/grpcio/tests/qps/benchmark_server.py b/src/python/grpcio/tests/qps/benchmark_server.py new file mode 100644 index 0000000000..8cbf480d58 --- /dev/null +++ b/src/python/grpcio/tests/qps/benchmark_server.py @@ -0,0 +1,58 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from src.proto.grpc.testing import messages_pb2 +from src.proto.grpc.testing import services_pb2 + + +class BenchmarkServer(services_pb2.BetaBenchmarkServiceServicer): + """Synchronous Server implementation for the Benchmark service.""" + + def UnaryCall(self, request, context): + payload = messages_pb2.Payload(body='\0' * request.response_size) + return messages_pb2.SimpleResponse(payload=payload) + + def StreamingCall(self, request_iterator, context): + for request in request_iterator: + payload = messages_pb2.Payload(body='\0' * request.response_size) + yield messages_pb2.SimpleResponse(payload=payload) + + +class GenericBenchmarkServer(services_pb2.BetaBenchmarkServiceServicer): + """Generic Server implementation for the Benchmark service.""" + + def __init__(self, resp_size): + self._response = '\0' * resp_size + + def UnaryCall(self, request, context): + return self._response + + def StreamingCall(self, request_iterator, context): + for request in request_iterator: + yield self._response diff --git a/src/python/grpcio/tests/qps/client_runner.py b/src/python/grpcio/tests/qps/client_runner.py new file mode 100644 index 0000000000..a36c30ccc0 --- /dev/null +++ b/src/python/grpcio/tests/qps/client_runner.py @@ -0,0 +1,104 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Defines behavior for WHEN clients send requests. + +Each client exposes a non-blocking send_request() method that the +ClientRunner invokes either periodically or in response to some event. +""" + +import abc +import thread +import time + + +class ClientRunner: + """Abstract interface for sending requests from clients.""" + + __metaclass__ = abc.ABCMeta + + def __init__(self, client): + self._client = client + + @abc.abstractmethod + def start(self): + raise NotImplementedError() + + @abc.abstractmethod + def stop(self): + raise NotImplementedError() + + +class OpenLoopClientRunner(ClientRunner): + + def __init__(self, client, interval_generator): + super(OpenLoopClientRunner, self).__init__(client) + self._is_running = False + self._interval_generator = interval_generator + + def start(self): + self._is_running = True + self._client.start() + thread.start_new_thread(self._dispatch_requests, ()) + + def stop(self): + self._is_running = False + self._client.stop() + self._client = None + + def _dispatch_requests(self): + while self._is_running: + self._client.send_request() + time.sleep(next(self._interval_generator)) + + +class ClosedLoopClientRunner(ClientRunner): + + def __init__(self, client, request_count): + super(ClosedLoopClientRunner, self).__init__(client) + self._is_running = False + self._request_count = request_count + # Send a new request on each response for closed loop + self._client.add_response_callback(self._send_request) + + def start(self): + self._is_running = True + for _ in xrange(self._request_count): + self._client.send_request() + self._client.start() + + def stop(self): + self._is_running = False + self._client.stop() + self._client = None + + def _send_request(self, response_time): + if self._is_running: + self._client.send_request() + diff --git a/src/python/grpcio/tests/qps/histogram.py b/src/python/grpcio/tests/qps/histogram.py new file mode 100644 index 0000000000..9a7b5eb2ba --- /dev/null +++ b/src/python/grpcio/tests/qps/histogram.py @@ -0,0 +1,85 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import math +import threading + +from src.proto.grpc.testing import stats_pb2 + + +class Histogram(object): + """Histogram class used for recording performance testing data. + + This class is thread safe. + """ + + def __init__(self, resolution, max_possible): + self._lock = threading.Lock() + self._resolution = resolution + self._max_possible = max_possible + self._sum = 0 + self._sum_of_squares = 0 + self.multiplier = 1.0 + self._resolution + self._count = 0 + self._min = self._max_possible + self._max = 0 + self._buckets = [0] * (self._bucket_for(self._max_possible) + 1) + + def reset(self): + with self._lock: + self._sum = 0 + self._sum_of_squares = 0 + self._count = 0 + self._min = self._max_possible + self._max = 0 + self._buckets = [0] * (self._bucket_for(self._max_possible) + 1) + + def add(self, val): + with self._lock: + self._sum += val + self._sum_of_squares += val * val + self._count += 1 + self._min = min(self._min, val) + self._max = max(self._max, val) + self._buckets[self._bucket_for(val)] += 1 + + def get_data(self): + with self._lock: + data = stats_pb2.HistogramData() + data.bucket.extend(self._buckets) + data.min_seen = self._min + data.max_seen = self._max + data.sum = self._sum + data.sum_of_squares = self._sum_of_squares + data.count = self._count + return data + + def _bucket_for(self, val): + val = min(val, self._max_possible) + return int(math.log(val, self.multiplier)) diff --git a/src/python/grpcio/tests/qps/qps_worker.py b/src/python/grpcio/tests/qps/qps_worker.py new file mode 100644 index 0000000000..3dda718638 --- /dev/null +++ b/src/python/grpcio/tests/qps/qps_worker.py @@ -0,0 +1,60 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""The entry point for the qps worker.""" + +import argparse +import time + +from src.proto.grpc.testing import services_pb2 + +from tests.qps import worker_server + + +def run_worker_server(port): + servicer = worker_server.WorkerServer() + server = services_pb2.beta_create_WorkerService_server(servicer) + server.add_insecure_port('[::]:{}'.format(port)) + server.start() + servicer.wait_for_quit() + # Drain outstanding requests for clean exit + time.sleep(2) + server.stop(0) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description='gRPC Python performance testing worker') + parser.add_argument('--driver_port', + type=int, + dest='port', + help='The port the worker should listen on') + args = parser.parse_args() + + run_worker_server(args.port) diff --git a/src/python/grpcio/tests/qps/worker_server.py b/src/python/grpcio/tests/qps/worker_server.py new file mode 100644 index 0000000000..0b3acc14e7 --- /dev/null +++ b/src/python/grpcio/tests/qps/worker_server.py @@ -0,0 +1,184 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import multiprocessing +import random +import threading +import time + +from grpc.beta import implementations +from grpc.framework.interfaces.face import utilities +from src.proto.grpc.testing import control_pb2 +from src.proto.grpc.testing import services_pb2 +from src.proto.grpc.testing import stats_pb2 + +from tests.qps import benchmark_client +from tests.qps import benchmark_server +from tests.qps import client_runner +from tests.qps import histogram +from tests.unit import resources + + +class WorkerServer(services_pb2.BetaWorkerServiceServicer): + """Python Worker Server implementation.""" + + def __init__(self): + self._quit_event = threading.Event() + + def RunServer(self, request_iterator, context): + config = next(request_iterator).setup + server, port = self._create_server(config) + cores = multiprocessing.cpu_count() + server.start() + start_time = time.time() + yield self._get_server_status(start_time, start_time, port, cores) + + for request in request_iterator: + end_time = time.time() + status = self._get_server_status(start_time, end_time, port, cores) + if request.mark.reset: + start_time = end_time + yield status + server.stop(0) + + def _get_server_status(self, start_time, end_time, port, cores): + end_time = time.time() + elapsed_time = end_time - start_time + stats = stats_pb2.ServerStats(time_elapsed=elapsed_time, + time_user=elapsed_time, + time_system=elapsed_time) + return control_pb2.ServerStatus(stats=stats, port=port, cores=cores) + + def _create_server(self, config): + if config.server_type == control_pb2.SYNC_SERVER: + servicer = benchmark_server.BenchmarkServer() + server = services_pb2.beta_create_BenchmarkService_server(servicer) + elif config.server_type == control_pb2.ASYNC_GENERIC_SERVER: + resp_size = config.payload_config.bytebuf_params.resp_size + servicer = benchmark_server.GenericBenchmarkServer(resp_size) + method_implementations = { + ('grpc.testing.BenchmarkService', 'StreamingCall'): + utilities.stream_stream_inline(servicer.StreamingCall), + ('grpc.testing.BenchmarkService', 'UnaryCall'): + utilities.unary_unary_inline(servicer.UnaryCall), + } + server = implementations.server(method_implementations) + else: + raise Exception('Unsupported server type {}'.format(config.server_type)) + + if config.HasField('security_params'): # Use SSL + server_creds = implementations.ssl_server_credentials([( + resources.private_key(), resources.certificate_chain())]) + port = server.add_secure_port('[::]:{}'.format(config.port), server_creds) + else: + port = server.add_insecure_port('[::]:{}'.format(config.port)) + + return (server, port) + + def RunClient(self, request_iterator, context): + config = next(request_iterator).setup + client_runners = [] + qps_data = histogram.Histogram(config.histogram_params.resolution, + config.histogram_params.max_possible) + start_time = time.time() + + # Create a client for each channel + for i in xrange(config.client_channels): + server = config.server_targets[i % len(config.server_targets)] + runner = self._create_client_runner(server, config, qps_data) + client_runners.append(runner) + runner.start() + + end_time = time.time() + yield self._get_client_status(start_time, end_time, qps_data) + + # Respond to stat requests + for request in request_iterator: + end_time = time.time() + status = self._get_client_status(start_time, end_time, qps_data) + if request.mark.reset: + qps_data.reset() + start_time = time.time() + yield status + + # Cleanup the clients + for runner in client_runners: + runner.stop() + + def _get_client_status(self, start_time, end_time, qps_data): + latencies = qps_data.get_data() + end_time = time.time() + elapsed_time = end_time - start_time + stats = stats_pb2.ClientStats(latencies=latencies, + time_elapsed=elapsed_time, + time_user=elapsed_time, + time_system=elapsed_time) + return control_pb2.ClientStatus(stats=stats) + + def _create_client_runner(self, server, config, qps_data): + if config.client_type == control_pb2.SYNC_CLIENT: + if config.rpc_type == control_pb2.UNARY: + client = benchmark_client.UnarySyncBenchmarkClient( + server, config, qps_data) + else: + raise Exception('STREAMING SYNC client not supported') + elif config.client_type == control_pb2.ASYNC_CLIENT: + if config.rpc_type == control_pb2.UNARY: + client = benchmark_client.UnaryAsyncBenchmarkClient( + server, config, qps_data) + elif config.rpc_type == control_pb2.STREAMING: + client = benchmark_client.StreamingAsyncBenchmarkClient( + server, config, qps_data) + else: + raise Exception('Unsupported client type {}'.format(config.client_type)) + + # In multi-channel tests, we split the load across all channels + load_factor = float(config.client_channels) + if config.load_params.WhichOneof('load') == 'closed_loop': + runner = client_runner.ClosedLoopClientRunner( + client, config.outstanding_rpcs_per_channel) + else: # Open loop Poisson + alpha = config.load_params.poisson.offered_load / load_factor + def poisson(): + while True: + yield random.expovariate(alpha) + + runner = client_runner.OpenLoopClientRunner(client, poisson()) + + return runner + + def CoreCount(self, request, context): + return control_pb2.CoreResponse(cores=multiprocessing.cpu_count()) + + def QuitWorker(self, request, context): + self._quit_event.set() + return control_pb2.Void() + + def wait_for_quit(self): + self._quit_event.wait() diff --git a/tools/gce/linux_performance_worker_init.sh b/tools/gce/linux_performance_worker_init.sh index 478e04ef37..25ac3bcede 100755 --- a/tools/gce/linux_performance_worker_init.sh +++ b/tools/gce/linux_performance_worker_init.sh @@ -83,11 +83,13 @@ sudo apt-get install -y libgflags-dev libgtest-dev libc++-dev clang # Python dependencies sudo pip install tabulate sudo pip install google-api-python-client +sudo pip install tox curl -O https://bootstrap.pypa.io/get-pip.py sudo pypy get-pip.py sudo pypy -m pip install tabulate sudo pip install google-api-python-client +sudo pip install tox # Node dependencies (nvm has to be installed under user jenkins) touch .profile diff --git a/tools/jenkins/run_performance.sh b/tools/jenkins/run_performance.sh index 903a144215..13a332751b 100755 --- a/tools/jenkins/run_performance.sh +++ b/tools/jenkins/run_performance.sh @@ -34,4 +34,4 @@ set -ex # Enter the gRPC repo root cd $(dirname $0)/../.. -tools/run_tests/run_performance_tests.py -l c++ node ruby csharp +tools/run_tests/run_performance_tests.py -l c++ node ruby csharp python diff --git a/tools/run_tests/performance/run_worker_python.sh b/tools/run_tests/performance/run_worker_python.sh new file mode 100755 index 0000000000..0da8deda58 --- /dev/null +++ b/tools/run_tests/performance/run_worker_python.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -ex + +cd $(dirname $0)/../../.. + +PYTHONPATH=src/python/grpcio:src/python/gens .tox/py27/bin/python src/python/grpcio/tests/qps/qps_worker.py $@ diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py index 55657f8d8a..ddbe237569 100644 --- a/tools/run_tests/performance/scenario_config.py +++ b/tools/run_tests/performance/scenario_config.py @@ -456,6 +456,128 @@ class NodeLanguage: def __str__(self): return 'node' +class PythonLanguage: + + def __init__(self): + self.safename = 'python' + + def worker_cmdline(self): + return ['tools/run_tests/performance/run_worker_python.sh'] + + def worker_port_offset(self): + return 500 + + def scenarios(self): + yield { + 'name': 'python_to_cpp_protobuf_streaming_ping_pong', + 'num_servers': 1, + 'num_clients': 1, + 'client_config': { + 'client_type': 'ASYNC_CLIENT', + 'security_params': SECURE_SECARGS, + 'outstanding_rpcs_per_channel': 1, + 'client_channels': 1, + 'async_client_threads': 1, + 'rpc_type': 'STREAMING', + 'load_params': { + 'closed_loop': {} + }, + 'payload_config': EMPTY_PROTO_PAYLOAD, + 'histogram_params': HISTOGRAM_PARAMS, + }, + 'server_config': { + 'server_type': 'SYNC_SERVER', + 'security_params': SECURE_SECARGS, + 'core_limit': 0, + 'async_server_threads': 1, + }, + 'warmup_seconds': WARMUP_SECONDS, + 'benchmark_seconds': BENCHMARK_SECONDS, + 'SERVER_LANGUAGE': 'c++' + } + yield { + 'name': 'python_protobuf_sync_unary_ping_pong', + 'num_servers': 1, + 'num_clients': 1, + 'client_config': { + 'client_type': 'SYNC_CLIENT', + 'security_params': SECURE_SECARGS, + 'outstanding_rpcs_per_channel': 1, + 'client_channels': 1, + 'async_client_threads': 1, + 'rpc_type': 'UNARY', + 'load_params': { + 'closed_loop': {} + }, + 'payload_config': EMPTY_PROTO_PAYLOAD, + 'histogram_params': HISTOGRAM_PARAMS, + }, + 'server_config': { + 'server_type': 'SYNC_SERVER', + 'security_params': SECURE_SECARGS, + 'core_limit': 0, + 'async_server_threads': 1, + }, + 'warmup_seconds': WARMUP_SECONDS, + 'benchmark_seconds': BENCHMARK_SECONDS, + } + yield { + 'name': 'python_protobuf_async_unary_ping_pong', + 'num_servers': 1, + 'num_clients': 1, + 'client_config': { + 'client_type': 'ASYNC_CLIENT', + 'security_params': SECURE_SECARGS, + 'outstanding_rpcs_per_channel': 1, + 'client_channels': 1, + 'async_client_threads': 1, + 'rpc_type': 'UNARY', + 'load_params': { + 'closed_loop': {} + }, + 'payload_config': EMPTY_PROTO_PAYLOAD, + 'histogram_params': HISTOGRAM_PARAMS, + }, + 'server_config': { + 'server_type': 'SYNC_SERVER', + 'security_params': SECURE_SECARGS, + 'core_limit': 0, + 'async_server_threads': 1, + }, + 'warmup_seconds': WARMUP_SECONDS, + 'benchmark_seconds': BENCHMARK_SECONDS, + } + yield { + 'name': 'python_to_cpp_single_channel_throughput', + 'num_servers': 1, + 'num_clients': 1, + 'client_config': { + 'client_type': 'ASYNC_CLIENT', + 'security_params': SECURE_SECARGS, + 'outstanding_rpcs_per_channel': 1, + 'client_channels': 1, + 'async_client_threads': 1, + 'rpc_type': 'STREAMING', + 'load_params': { + 'closed_loop': {} + }, + 'payload_config': BIG_GENERIC_PAYLOAD, + 'histogram_params': HISTOGRAM_PARAMS, + }, + 'server_config': { + 'server_type': 'ASYNC_GENERIC_SERVER', + 'security_params': SECURE_SECARGS, + 'core_limit': SINGLE_MACHINE_CORES/2, + 'async_server_threads': 1, + 'payload_config': BIG_GENERIC_PAYLOAD, + }, + 'warmup_seconds': WARMUP_SECONDS, + 'benchmark_seconds': BENCHMARK_SECONDS, + 'SERVER_LANGUAGE': 'c++' + } + + def __str__(self): + return 'python' class RubyLanguage: @@ -562,4 +684,5 @@ LANGUAGES = { 'node' : NodeLanguage(), 'ruby' : RubyLanguage(), 'java' : JavaLanguage(), + 'python' : PythonLanguage(), } diff --git a/tools/run_tests/run_performance_tests.py b/tools/run_tests/run_performance_tests.py index ada341abf5..485265311e 100755 --- a/tools/run_tests/run_performance_tests.py +++ b/tools/run_tests/run_performance_tests.py @@ -238,6 +238,9 @@ def start_qpsworkers(languages, worker_hosts): def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*', bq_result_table=None): """Create jobspecs for scenarios to run.""" + all_workers = [worker + for workers in workers_by_lang.values() + for worker in workers] scenarios = [] for language in languages: for scenario_json in language.scenarios(): @@ -263,9 +266,6 @@ def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*', scenarios.append(scenario) # the very last scenario requests shutting down the workers. - all_workers = [worker - for workers in workers_by_lang.values() - for worker in workers] scenarios.append(create_quit_jobspec(all_workers, remote_host=remote_host)) return scenarios -- cgit v1.2.3 From ad9d06effe37bf9c99a8b2aad8f52657b30e7abf Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Thu, 28 Apr 2016 22:15:04 -0700 Subject: Create Python stress test --- src/python/grpcio/tests/stress/__init__.py | 28 +++++ src/python/grpcio/tests/stress/client.py | 132 +++++++++++++++++++++++ src/python/grpcio/tests/stress/metrics_server.py | 60 +++++++++++ src/python/grpcio/tests/stress/test_runner.py | 73 +++++++++++++ 4 files changed, 293 insertions(+) create mode 100644 src/python/grpcio/tests/stress/__init__.py create mode 100644 src/python/grpcio/tests/stress/client.py create mode 100644 src/python/grpcio/tests/stress/metrics_server.py create mode 100644 src/python/grpcio/tests/stress/test_runner.py (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/tests/stress/__init__.py b/src/python/grpcio/tests/stress/__init__.py new file mode 100644 index 0000000000..100a624dc9 --- /dev/null +++ b/src/python/grpcio/tests/stress/__init__.py @@ -0,0 +1,28 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/python/grpcio/tests/stress/client.py b/src/python/grpcio/tests/stress/client.py new file mode 100644 index 0000000000..a733741b73 --- /dev/null +++ b/src/python/grpcio/tests/stress/client.py @@ -0,0 +1,132 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Entry point for running stress tests.""" + +import argparse +import Queue +import threading + +from grpc.beta import implementations +from src.proto.grpc.testing import metrics_pb2 +from src.proto.grpc.testing import test_pb2 + +from tests.interop import methods +from tests.qps import histogram +from tests.stress import metrics_server +from tests.stress import test_runner + + +def _args(): + parser = argparse.ArgumentParser(description='gRPC Python stress test client') + parser.add_argument( + '--server_addresses', + help='comma seperated list of hostname:port to run servers on', + default='localhost:8080', type=str) + parser.add_argument( + '--test_cases', + help='comma seperated list of testcase:weighting of tests to run', + default='large_unary:100', + type=str) + parser.add_argument( + '--test_duration_secs', + help='number of seconds to run the stress test', + default=-1, type=int) + parser.add_argument( + '--num_channels_per_server', + help='number of channels per server', + default=1, type=int) + parser.add_argument( + '--num_stubs_per_channel', + help='number of stubs to create per channel', + default=1, type=int) + parser.add_argument( + '--metrics_port', + help='the port to listen for metrics requests on', + default=8081, type=int) + return parser.parse_args() + + +def _test_case_from_arg(test_case_arg): + for test_case in methods.TestCase: + if test_case_arg == test_case.value: + return test_case + else: + raise ValueError('No test case {}!'.format(test_case_arg)) + + +def _parse_weighted_test_cases(test_case_args): + weighted_test_cases = {} + for test_case_arg in test_case_args.split(','): + name, weight = test_case_arg.split(':', 1) + test_case = _test_case_from_arg(name) + weighted_test_cases[test_case] = int(weight) + return weighted_test_cases + + +def run_test(args): + test_cases = _parse_weighted_test_cases(args.test_cases) + test_servers = args.server_addresses.split(',') + # Propagate any client exceptions with a queue + exception_queue = Queue.Queue() + stop_event = threading.Event() + hist = histogram.Histogram(1, 1) + runners = [] + + server = metrics_pb2.beta_create_MetricsService_server( + metrics_server.MetricsServer(hist)) + server.add_insecure_port('[::]:{}'.format(args.metrics_port)) + server.start() + + for test_server in test_servers: + host, port = test_server.split(':', 1) + for _ in xrange(args.num_channels_per_server): + channel = implementations.insecure_channel(host, int(port)) + for _ in xrange(args.num_stubs_per_channel): + stub = test_pb2.beta_create_TestService_stub(channel) + runner = test_runner.TestRunner(stub, test_cases, hist, + exception_queue, stop_event) + runners.append(runner) + + for runner in runners: + runner.start() + try: + raise exception_queue.get(block=True, timeout=args.test_duration_secs) + except Queue.Empty: + # No exceptions thrown, success + pass + finally: + stop_event.set() + for runner in runners: + runner.join() + runner = None + server.stop(0) + +if __name__ == '__main__': + run_test(_args()) diff --git a/src/python/grpcio/tests/stress/metrics_server.py b/src/python/grpcio/tests/stress/metrics_server.py new file mode 100644 index 0000000000..b994e4643e --- /dev/null +++ b/src/python/grpcio/tests/stress/metrics_server.py @@ -0,0 +1,60 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""MetricsService for publishing stress test qps data.""" + +import time + +from src.proto.grpc.testing import metrics_pb2 + +GAUGE_NAME = 'python_overall_qps' + + +class MetricsServer(metrics_pb2.BetaMetricsServiceServicer): + + def __init__(self, histogram): + self._start_time = time.time() + self._histogram = histogram + + def _get_qps(self): + count = self._histogram.get_data().count + delta = time.time() - self._start_time + self._histogram.reset() + self._start_time = time.time() + return int(count/delta) + + def GetAllGauges(self, request, context): + qps = self._get_qps() + return [metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps)] + + def GetGauge(self, request, context): + if request.name != GAUGE_NAME: + raise Exception('Gauge {} does not exist'.format(request.name)) + qps = self._get_qps() + return metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps) diff --git a/src/python/grpcio/tests/stress/test_runner.py b/src/python/grpcio/tests/stress/test_runner.py new file mode 100644 index 0000000000..88f13727e3 --- /dev/null +++ b/src/python/grpcio/tests/stress/test_runner.py @@ -0,0 +1,73 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Thread that sends random weighted requests on a TestService stub.""" + +import random +import threading +import time +import traceback + + +def _weighted_test_case_generator(weighted_cases): + weight_sum = sum(weighted_cases.itervalues()) + + while True: + val = random.uniform(0, weight_sum) + partial_sum = 0 + for case in weighted_cases: + partial_sum += weighted_cases[case] + if val <= partial_sum: + yield case + break + + +class TestRunner(threading.Thread): + + def __init__(self, stub, test_cases, hist, exception_queue, stop_event): + super(TestRunner, self).__init__() + self._exception_queue = exception_queue + self._stop_event = stop_event + self._stub = stub + self._test_cases = _weighted_test_case_generator(test_cases) + self._histogram = hist + + def run(self): + while not self._stop_event.is_set(): + try: + test_case = next(self._test_cases) + start_time = time.time() + test_case.test_interoperability(self._stub, None) + end_time = time.time() + self._histogram.add((end_time - start_time)*1e9) + except Exception as e: + traceback.print_exc() + self._exception_queue.put( + Exception("An exception occured during test {}" + .format(test_case), e)) -- cgit v1.2.3 From 63ee8ce43cb9bcd9832fb0a5303b8228a009c1c2 Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Sun, 1 May 2016 15:12:18 -0700 Subject: Reran tools/buildgen/generate_projects.sh again. --- grpc.def | 1 + src/python/grpcio/grpc/_cython/imports.generated.c | 2 ++ src/python/grpcio/grpc/_cython/imports.generated.h | 4 ++++ src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 ++ src/ruby/ext/grpc/rb_grpc_imports.generated.h | 4 ++++ 5 files changed, 13 insertions(+) (limited to 'src/python/grpcio') diff --git a/grpc.def b/grpc.def index 61948ed1b8..09a94a6cd0 100644 --- a/grpc.def +++ b/grpc.def @@ -87,6 +87,7 @@ EXPORTS grpc_header_nonbin_value_is_legal grpc_is_binary_header grpc_call_error_to_string + grpc_cronet_secure_channel_create grpc_auth_property_iterator_next grpc_auth_context_property_iterator grpc_auth_context_peer_identity diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c index f0a40dbb35..09551472b5 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.c +++ b/src/python/grpcio/grpc/_cython/imports.generated.c @@ -125,6 +125,7 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; +grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -395,6 +396,7 @@ void pygrpc_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); + grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h index d5e810b7cf..54c8aaad13 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/python/grpcio/grpc/_cython/imports.generated.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,9 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import +typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); +extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; +#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index bc43f9d36b..cebbe8c40f 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -125,6 +125,7 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; +grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -391,6 +392,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); + grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index b67361ca25..d7ea6c574c 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,9 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import +typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); +extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; +#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import -- cgit v1.2.3 From 70f697ba1e6ad17422928a398807e84f8f469724 Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Mon, 2 May 2016 22:29:21 -0700 Subject: reran generate_projects.sh after @nnoble's fix in PR6399. --- grpc.def | 1 - src/python/grpcio/grpc/_cython/imports.generated.c | 2 -- src/python/grpcio/grpc/_cython/imports.generated.h | 4 ---- src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 -- src/ruby/ext/grpc/rb_grpc_imports.generated.h | 4 ---- 5 files changed, 13 deletions(-) (limited to 'src/python/grpcio') diff --git a/grpc.def b/grpc.def index 09a94a6cd0..61948ed1b8 100644 --- a/grpc.def +++ b/grpc.def @@ -87,7 +87,6 @@ EXPORTS grpc_header_nonbin_value_is_legal grpc_is_binary_header grpc_call_error_to_string - grpc_cronet_secure_channel_create grpc_auth_property_iterator_next grpc_auth_context_property_iterator grpc_auth_context_peer_identity diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c index 09551472b5..f0a40dbb35 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.c +++ b/src/python/grpcio/grpc/_cython/imports.generated.c @@ -125,7 +125,6 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; -grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -396,7 +395,6 @@ void pygrpc_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); - grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h index 54c8aaad13..d5e810b7cf 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/python/grpcio/grpc/_cython/imports.generated.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -326,9 +325,6 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import -typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); -extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; -#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index cebbe8c40f..bc43f9d36b 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -125,7 +125,6 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; -grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -392,7 +391,6 @@ void grpc_rb_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); - grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index d7ea6c574c..b67361ca25 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -326,9 +325,6 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import -typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); -extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; -#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import -- cgit v1.2.3 From d8c0d385f45a953d683203f24bda90e679d98f25 Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Tue, 3 May 2016 17:12:45 -0700 Subject: Fix a bug in stress client code --- src/python/grpcio/tests/stress/client.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/tests/stress/client.py b/src/python/grpcio/tests/stress/client.py index a733741b73..e2e016760c 100644 --- a/src/python/grpcio/tests/stress/client.py +++ b/src/python/grpcio/tests/stress/client.py @@ -117,7 +117,10 @@ def run_test(args): for runner in runners: runner.start() try: - raise exception_queue.get(block=True, timeout=args.test_duration_secs) + timeout_secs = args.test_duration_secs + if timeout_secs < 0: + timeout_secs = None + raise exception_queue.get(block=True, timeout=timeout_secs) except Queue.Empty: # No exceptions thrown, success pass -- cgit v1.2.3 From 274bcc8f0b50bfef7fe1dd5cc33ebaa6b13edba0 Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Tue, 3 May 2016 17:34:54 -0700 Subject: Added dummy cronet api implementation so we can build on Jenkins. --- BUILD | 12 +++ Makefile | 7 ++ binding.gyp | 3 + build.yaml | 10 +++ config.m4 | 5 ++ gRPC.podspec | 8 ++ grpc.def | 1 + grpc.gemspec | 6 ++ package.xml | 6 ++ .../cronet/client/secure/cronet_channel_create.c | 3 - .../transport/cronet/transport/cronet_api_dummy.c | 91 ++++++++++++++++++++++ .../transport/cronet/transport/cronet_transport.c | 6 +- src/python/grpcio/grpc/_cython/imports.generated.c | 2 + src/python/grpcio/grpc/_cython/imports.generated.h | 4 + src/python/grpcio/grpc_core_dependencies.py | 3 + src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 + src/ruby/ext/grpc/rb_grpc_imports.generated.h | 4 + test/core/surface/public_headers_must_be_c89.c | 1 + tools/doxygen/Doxyfile.core | 1 + tools/doxygen/Doxyfile.core.internal | 6 ++ tools/run_tests/sources_and_headers.json | 22 +++++- vsprojects/vcxproj/grpc/grpc.vcxproj | 9 +++ vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 39 ++++++++++ 23 files changed, 243 insertions(+), 8 deletions(-) create mode 100644 src/core/ext/transport/cronet/transport/cronet_api_dummy.c (limited to 'src/python/grpcio') diff --git a/BUILD b/BUILD index b4b10b535e..2e1d762f07 100644 --- a/BUILD +++ b/BUILD @@ -285,6 +285,8 @@ cc_library( "src/core/ext/client_config/subchannel_call_holder.h", "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", + "include/grpc/support/port_platform.h", + "third_party/objective_c/Cronet/cronet_c_for_grpc.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", "src/core/ext/census/aggregation.h", @@ -439,6 +441,9 @@ cc_library( "src/core/ext/client_config/uri_parser.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", + "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", + "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", + "src/core/ext/transport/cronet/transport/cronet_transport.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", @@ -482,6 +487,7 @@ cc_library( "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_win32.h", "include/grpc/impl/codegen/time.h", + "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "include/grpc/census.h", @@ -1456,6 +1462,9 @@ objc_library( "src/core/ext/client_config/uri_parser.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", + "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", + "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", + "src/core/ext/transport/cronet/transport/cronet_transport.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", @@ -1499,6 +1508,7 @@ objc_library( "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_win32.h", "include/grpc/impl/codegen/time.h", + "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "include/grpc/census.h", @@ -1626,6 +1636,8 @@ objc_library( "src/core/ext/client_config/subchannel_call_holder.h", "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", + "include/grpc/support/port_platform.h", + "third_party/objective_c/Cronet/cronet_c_for_grpc.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", "src/core/ext/census/aggregation.h", diff --git a/Makefile b/Makefile index 922e0b0568..c6fd3b40f7 100644 --- a/Makefile +++ b/Makefile @@ -2623,6 +2623,9 @@ LIBGRPC_SRC = \ src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ + src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ + src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ + src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -2669,6 +2672,7 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ + include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -14313,6 +14317,9 @@ ifneq ($(OPENSSL_DEP),) # otherwise parallel compilation will fail if a source is compiled first. src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP) +src/core/ext/transport/cronet/client/secure/cronet_channel_create.c: $(OPENSSL_DEP) +src/core/ext/transport/cronet/transport/cronet_api_dummy.c: $(OPENSSL_DEP) +src/core/ext/transport/cronet/transport/cronet_transport.c: $(OPENSSL_DEP) src/core/lib/http/httpcli_security_connector.c: $(OPENSSL_DEP) src/core/lib/security/b64.c: $(OPENSSL_DEP) src/core/lib/security/client_auth_filter.c: $(OPENSSL_DEP) diff --git a/binding.gyp b/binding.gyp index 4314ab7243..12a745ffb0 100644 --- a/binding.gyp +++ b/binding.gyp @@ -709,6 +709,9 @@ 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', + 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', + 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', + 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/build.yaml b/build.yaml index 441752dc3d..a7ab412722 100644 --- a/build.yaml +++ b/build.yaml @@ -399,6 +399,7 @@ filegroups: - grpc_client_config - name: grpc_secure public_headers: + - include/grpc/grpc_cronet.h - include/grpc/grpc_security.h - include/grpc/grpc_security_constants.h headers: @@ -546,6 +547,14 @@ filegroups: - grpc_transport_chttp2 - grpc_base - grpc_secure +- name: grpc_transport_cronet_client_secure + headers: + - include/grpc/support/port_platform.h + - third_party/objective_c/Cronet/cronet_c_for_grpc.h + src: + - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c + - src/core/ext/transport/cronet/transport/cronet_api_dummy.c + - src/core/ext/transport/cronet/transport/cronet_transport.c - name: nanopb headers: - third_party/nanopb/pb.h @@ -733,6 +742,7 @@ libs: - grpc_transport_chttp2_client_secure - grpc_transport_chttp2_server_insecure - grpc_transport_chttp2_client_insecure + - grpc_transport_cronet_client_secure - grpc_lb_policy_grpclb - grpc_lb_policy_pick_first - grpc_lb_policy_round_robin diff --git a/config.m4 b/config.m4 index 74f9ad242a..5259e679ba 100644 --- a/config.m4 +++ b/config.m4 @@ -228,6 +228,9 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ + src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ + src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ + src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -566,6 +569,8 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/insecure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/secure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/cronet/client/secure) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/cronet/transport) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/channel) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug) diff --git a/gRPC.podspec b/gRPC.podspec index 77d35bd2c7..f57ba74519 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -287,6 +287,8 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_call_holder.h', 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', + 'include/grpc/support/port_platform.h', + 'third_party/objective_c/Cronet/cronet_c_for_grpc.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', 'third_party/nanopb/pb.h', @@ -324,6 +326,7 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/sync_posix.h', 'include/grpc/impl/codegen/sync_win32.h', 'include/grpc/impl/codegen/time.h', + 'include/grpc/grpc_cronet.h', 'include/grpc/grpc_security.h', 'include/grpc/grpc_security_constants.h', 'include/grpc/census.h', @@ -473,6 +476,9 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', + 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', + 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', + 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', @@ -629,6 +635,8 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_call_holder.h', 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', + 'include/grpc/support/port_platform.h', + 'third_party/objective_c/Cronet/cronet_c_for_grpc.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', 'third_party/nanopb/pb.h', diff --git a/grpc.def b/grpc.def index 61948ed1b8..09a94a6cd0 100644 --- a/grpc.def +++ b/grpc.def @@ -87,6 +87,7 @@ EXPORTS grpc_header_nonbin_value_is_legal grpc_is_binary_header grpc_call_error_to_string + grpc_cronet_secure_channel_create grpc_auth_property_iterator_next grpc_auth_context_property_iterator grpc_auth_context_peer_identity diff --git a/grpc.gemspec b/grpc.gemspec index e68cd81da7..488f4657cd 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -168,6 +168,7 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/sync_posix.h ) s.files += %w( include/grpc/impl/codegen/sync_win32.h ) s.files += %w( include/grpc/impl/codegen/time.h ) + s.files += %w( include/grpc/grpc_cronet.h ) s.files += %w( include/grpc/grpc_security.h ) s.files += %w( include/grpc/grpc_security_constants.h ) s.files += %w( include/grpc/census.h ) @@ -295,6 +296,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_config/subchannel_call_holder.h ) s.files += %w( src/core/ext/client_config/subchannel_index.h ) s.files += %w( src/core/ext/client_config/uri_parser.h ) + s.files += %w( include/grpc/support/port_platform.h ) + s.files += %w( third_party/objective_c/Cronet/cronet_c_for_grpc.h ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h ) s.files += %w( third_party/nanopb/pb.h ) @@ -453,6 +456,9 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_config/uri_parser.c ) s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) + s.files += %w( src/core/ext/transport/cronet/client/secure/cronet_channel_create.c ) + s.files += %w( src/core/ext/transport/cronet/transport/cronet_api_dummy.c ) + s.files += %w( src/core/ext/transport/cronet/transport/cronet_transport.c ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c ) s.files += %w( third_party/nanopb/pb_common.c ) diff --git a/package.xml b/package.xml index ffb1c56ed6..e8fd375eb6 100644 --- a/package.xml +++ b/package.xml @@ -175,6 +175,7 @@ + @@ -302,6 +303,8 @@ + + @@ -460,6 +463,9 @@ + + + diff --git a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c index a6cb1f70a7..df1acddcc0 100644 --- a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c +++ b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c @@ -33,8 +33,6 @@ #include -#ifdef GRPC_COMPILE_WITH_CRONET - #include #include @@ -69,4 +67,3 @@ GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( return grpc_channel_create(&exec_ctx, target, args, GRPC_CLIENT_DIRECT_CHANNEL, (grpc_transport *)ct); } -#endif // GRPC_COMPILE_WITH_CRONET diff --git a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c new file mode 100644 index 0000000000..200f9f7daa --- /dev/null +++ b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c @@ -0,0 +1,91 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* This file has empty implementation of all the functions exposed by the cronet +library, so we can build it in all environments */ + +#include + +#include + +#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h" + +#ifdef GRPC_COMPILE_WITH_CRONET + /* link with the real CRONET library in the build system */ +#else + /* Dummy implementation of cronet API just to test for build-ability */ +cronet_bidirectional_stream* cronet_bidirectional_stream_create( + cronet_engine* engine, + void* annotation, + cronet_bidirectional_stream_callback* callback) { + GPR_ASSERT(0); + return NULL; +} + +int cronet_bidirectional_stream_destroy(cronet_bidirectional_stream* stream) { + GPR_ASSERT(0); + return 0; +} + +int cronet_bidirectional_stream_start( + cronet_bidirectional_stream* stream, + const char* url, + int priority, + const char* method, + const cronet_bidirectional_stream_header_array* headers, + bool end_of_stream) { + GPR_ASSERT(0); + return 0; +} + +int cronet_bidirectional_stream_read(cronet_bidirectional_stream* stream, + char* buffer, + int capacity) { + GPR_ASSERT(0); + return 0; +} + +int cronet_bidirectional_stream_write(cronet_bidirectional_stream* stream, + const char* buffer, + int count, + bool end_of_stream) { + GPR_ASSERT(0); + return 0; +} + +int cronet_bidirectional_stream_cancel(cronet_bidirectional_stream* stream) { + GPR_ASSERT(0); + return 0; +} + +#endif /* GRPC_COMPILE_WITH_CRONET */ diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c index d337e84606..64bd5f5778 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -49,8 +49,6 @@ #include "src/core/lib/transport/transport_impl.h" #include "third_party/objective_c/Cronet/cronet_c_for_grpc.h" -#ifdef GRPC_COMPILE_WITH_CRONET - #define GRPC_HEADER_SIZE_IN_BYTES 5 // Global flag that gets set with GRPC_TRACE env variable @@ -613,7 +611,7 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, } static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs) { + grpc_stream *gs, void *and_free_memory) { if (grpc_cronet_trace) { gpr_log(GPR_DEBUG, "Destroy stream"); } @@ -623,6 +621,7 @@ static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, gpr_free(s->write_buffer); gpr_free(s->url); gpr_mu_destroy(&s->recv_mu); + if (and_free_memory) { gpr_free(and_free_memory); } } static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { @@ -637,4 +636,3 @@ const grpc_transport_vtable grpc_cronet_vtable = { sizeof(stream_obj), "cronet_http", init_stream, set_pollset_do_nothing, perform_stream_op, NULL, destroy_stream, destroy_transport, NULL}; -#endif // GRPC_COMPILE_WITH_CRONET diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c index f0a40dbb35..09551472b5 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.c +++ b/src/python/grpcio/grpc/_cython/imports.generated.c @@ -125,6 +125,7 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; +grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -395,6 +396,7 @@ void pygrpc_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); + grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h index d5e810b7cf..54c8aaad13 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/python/grpcio/grpc/_cython/imports.generated.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,9 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import +typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); +extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; +#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index dab62530aa..5314329c2c 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -222,6 +222,9 @@ CORE_SOURCE_FILES = [ 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', + 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', + 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', + 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index bc43f9d36b..cebbe8c40f 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -125,6 +125,7 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; +grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -391,6 +392,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); + grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index b67361ca25..d7ea6c574c 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,9 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import +typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); +extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; +#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 0eede6c23b..65f3e1738a 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 034d9c6e6f..a582d76a58 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -785,6 +785,7 @@ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ +include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1b1453f7ea..16dcd9b79a 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -785,6 +785,7 @@ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ +include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -912,6 +913,8 @@ src/core/ext/client_config/subchannel.h \ src/core/ext/client_config/subchannel_call_holder.h \ src/core/ext/client_config/subchannel_index.h \ src/core/ext/client_config/uri_parser.h \ +include/grpc/support/port_platform.h \ +third_party/objective_c/Cronet/cronet_c_for_grpc.h \ src/core/ext/lb_policy/grpclb/load_balancer_api.h \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h \ third_party/nanopb/pb.h \ @@ -1070,6 +1073,9 @@ src/core/ext/client_config/subchannel_index.c \ src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ +src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ +src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ +src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index f546f3b995..e22318d238 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -4140,7 +4140,8 @@ "grpc_transport_chttp2_client_insecure", "grpc_transport_chttp2_client_secure", "grpc_transport_chttp2_server_insecure", - "grpc_transport_chttp2_server_secure" + "grpc_transport_chttp2_server_secure", + "grpc_transport_cronet_client_secure" ], "headers": [], "language": "c", @@ -6012,6 +6013,7 @@ "tsi" ], "headers": [ + "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "src/core/lib/security/auth_filters.h", @@ -6027,6 +6029,7 @@ "language": "c", "name": "grpc_secure", "src": [ + "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "src/core/lib/http/httpcli_security_connector.c", @@ -6262,6 +6265,23 @@ "third_party": false, "type": "filegroup" }, + { + "deps": [], + "headers": [ + "include/grpc/support/port_platform.h", + "third_party/objective_c/Cronet/cronet_c_for_grpc.h" + ], + "language": "c", + "name": "grpc_transport_cronet_client_secure", + "src": [ + "include/grpc/support/port_platform.h", + "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", + "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", + "src/core/ext/transport/cronet/transport/cronet_transport.c" + ], + "third_party": false, + "type": "filegroup" + }, { "deps": [], "headers": [ diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 4eec05a3b1..cbf854875a 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -292,6 +292,7 @@ + @@ -421,6 +422,8 @@ + + @@ -727,6 +730,12 @@ + + + + + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 17c88c4805..02297b7746 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -439,6 +439,15 @@ src\core\ext\transport\chttp2\client\insecure + + src\core\ext\transport\cronet\client\secure + + + src\core\ext\transport\cronet\transport + + + src\core\ext\transport\cronet\transport + src\core\ext\lb_policy\grpclb @@ -573,6 +582,9 @@ include\grpc\impl\codegen + + include\grpc + include\grpc @@ -956,6 +968,12 @@ src\core\ext\client_config + + include\grpc\support + + + third_party\objective_c\Cronet + src\core\ext\lb_policy\grpclb @@ -1007,6 +1025,9 @@ {def748f5-ed2a-a9bb-40d9-c31d00f0e13b} + + {31de82ea-dc6c-73fb-a640-979b8a7b240c} + {d538af37-07b2-062b-fa2a-d9f882cb2737} @@ -1088,6 +1109,18 @@ {6f34254e-e69f-c9b4-156d-5024bade5408} + + {1e9c85e9-5522-7ef8-0017-7e19990a6194} + + + {d0530883-75d9-b5f7-d594-26735a70ac7b} + + + {4fa6fe90-b7a8-5c8f-d629-db1e68d89eed} + + + {31518af8-5860-6d0d-ff78-4059fce29ec2} + {5b2ded3f-84a5-f6b4-2060-286c7d1dc945} @@ -1130,6 +1163,12 @@ {93d6596d-330c-1d27-6f84-3c840e57869e} + + {3a56a516-857e-d2aa-95cc-11685baf4e8c} + + + {a165c6e3-0776-6f40-7351-d7865668e220} + -- cgit v1.2.3 From d039a98a94cc2f1d8769a3a11eea73494cc287f4 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Tue, 5 Apr 2016 15:15:03 -0700 Subject: Add Python grpcio protoc package --- setup.py | 1 + src/python/grpcio/grpc/__init__.py | 3 +- tools/distrib/python/bazel_deps.sh | 39 +++++++ tools/distrib/python/grpcio_protoc/.gitignore | 7 ++ .../distrib/python/grpcio_protoc/grpc/__init__.py | 30 ++++++ .../python/grpcio_protoc/grpc/protoc/__init__.py | 29 +++++ .../grpc/protoc/grpc_python_protoc_compiler.py | 38 +++++++ .../grpc/protoc/grpc_python_protoc_plugin.py | 38 +++++++ .../python/grpcio_protoc/grpc/protoc/main.h | 33 ++++++ .../python/grpcio_protoc/grpc/protoc/protoc.pyx | 39 +++++++ .../grpcio_protoc/grpc/protoc/protoc_plugin.pyx | 39 +++++++ tools/distrib/python/grpcio_protoc/protoc_deps.py | 32 ++++++ .../python/grpcio_protoc/protoc_lib_deps.py | 32 ++++++ tools/distrib/python/grpcio_protoc/setup.py | 102 ++++++++++++++++++ tools/distrib/python/grpcio_tools/MANIFEST.in | 5 + tools/distrib/python/mk_grpcio_protoc.py | 118 +++++++++++++++++++++ tools/dockerfile/bazel/Dockerfile | 53 +++++++++ 17 files changed, 637 insertions(+), 1 deletion(-) create mode 100755 tools/distrib/python/bazel_deps.sh create mode 100644 tools/distrib/python/grpcio_protoc/.gitignore create mode 100644 tools/distrib/python/grpcio_protoc/grpc/__init__.py create mode 100644 tools/distrib/python/grpcio_protoc/grpc/protoc/__init__.py create mode 100644 tools/distrib/python/grpcio_protoc/grpc/protoc/grpc_python_protoc_compiler.py create mode 100644 tools/distrib/python/grpcio_protoc/grpc/protoc/grpc_python_protoc_plugin.py create mode 100644 tools/distrib/python/grpcio_protoc/grpc/protoc/main.h create mode 100644 tools/distrib/python/grpcio_protoc/grpc/protoc/protoc.pyx create mode 100644 tools/distrib/python/grpcio_protoc/grpc/protoc/protoc_plugin.pyx create mode 100644 tools/distrib/python/grpcio_protoc/protoc_deps.py create mode 100644 tools/distrib/python/grpcio_protoc/protoc_lib_deps.py create mode 100644 tools/distrib/python/grpcio_protoc/setup.py create mode 100644 tools/distrib/python/grpcio_tools/MANIFEST.in create mode 100755 tools/distrib/python/mk_grpcio_protoc.py create mode 100644 tools/dockerfile/bazel/Dockerfile (limited to 'src/python/grpcio') diff --git a/setup.py b/setup.py index cd0d3a1a51..af9eb68534 100644 --- a/setup.py +++ b/setup.py @@ -236,6 +236,7 @@ setup_arguments = { 'ext_modules': CYTHON_EXTENSION_MODULES, 'packages': list(PACKAGES), 'package_dir': PACKAGE_DIRECTORIES, + 'namespace_packages': ['grpc'], 'package_data': PACKAGE_DATA, 'install_requires': INSTALL_REQUIRES, 'setup_requires': SETUP_REQUIRES, diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index 7086519106..b844a14c48 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,4 +27,5 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +__import__('pkg_resources').declare_namespace(__name__) diff --git a/tools/distrib/python/bazel_deps.sh b/tools/distrib/python/bazel_deps.sh new file mode 100755 index 0000000000..4619c00887 --- /dev/null +++ b/tools/distrib/python/bazel_deps.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +cd $(dirname $0)/../../../ + +docker build -t bazel `realpath ./tools/dockerfile/bazel/` +docker run -v "`realpath .`:/src/grpc/" \ + -w /src/grpc/third_party/protobuf \ + bazel \ + bazel query 'deps('$1')' + diff --git a/tools/distrib/python/grpcio_protoc/.gitignore b/tools/distrib/python/grpcio_protoc/.gitignore new file mode 100644 index 0000000000..979704d970 --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/.gitignore @@ -0,0 +1,7 @@ +build/ +protobuf/ +grpc_plugin/ +grpc_root/ +*.c +*.cpp +*.egg-info diff --git a/tools/distrib/python/grpcio_protoc/grpc/__init__.py b/tools/distrib/python/grpcio_protoc/grpc/__init__.py new file mode 100644 index 0000000000..70ac5edd48 --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/grpc/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +__import__('pkg_resources').declare_namespace(__name__) diff --git a/tools/distrib/python/grpcio_protoc/grpc/protoc/__init__.py b/tools/distrib/python/grpcio_protoc/grpc/protoc/__init__.py new file mode 100644 index 0000000000..d5ad73a74a --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/grpc/protoc/__init__.py @@ -0,0 +1,29 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/tools/distrib/python/grpcio_protoc/grpc/protoc/grpc_python_protoc_compiler.py b/tools/distrib/python/grpcio_protoc/grpc/protoc/grpc_python_protoc_compiler.py new file mode 100644 index 0000000000..5395f2ac10 --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/grpc/protoc/grpc_python_protoc_compiler.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import sys + +from grpc.protoc import protoc + + +if __name__ == '__main__': + protoc.run_main(sys.argv) diff --git a/tools/distrib/python/grpcio_protoc/grpc/protoc/grpc_python_protoc_plugin.py b/tools/distrib/python/grpcio_protoc/grpc/protoc/grpc_python_protoc_plugin.py new file mode 100644 index 0000000000..3b279e2976 --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/grpc/protoc/grpc_python_protoc_plugin.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import sys + +from grpc.protoc import protoc_plugin + + +if __name__ == '__main__': + protoc_plugin.run_main(sys.argv) diff --git a/tools/distrib/python/grpcio_protoc/grpc/protoc/main.h b/tools/distrib/python/grpcio_protoc/grpc/protoc/main.h new file mode 100644 index 0000000000..fc406a9260 --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/grpc/protoc/main.h @@ -0,0 +1,33 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// We declare `main` here since we want access to it from Cython as an extern +// but *without* triggering a dllimport declspec when on Windows. +int main(int argc, char *argv[]); diff --git a/tools/distrib/python/grpcio_protoc/grpc/protoc/protoc.pyx b/tools/distrib/python/grpcio_protoc/grpc/protoc/protoc.pyx new file mode 100644 index 0000000000..d987ee1cea --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/grpc/protoc/protoc.pyx @@ -0,0 +1,39 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from libc cimport stdlib + +cdef extern from "grpc/protoc/main.h": + int main(int argc, char *argv[]) + +def run_main(list args not None): + cdef char **argv = stdlib.malloc(len(args)*sizeof(char *)) + for i in range(len(args)): + argv[i] = args[i] + return main(len(args), argv) diff --git a/tools/distrib/python/grpcio_protoc/grpc/protoc/protoc_plugin.pyx b/tools/distrib/python/grpcio_protoc/grpc/protoc/protoc_plugin.pyx new file mode 100644 index 0000000000..d987ee1cea --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/grpc/protoc/protoc_plugin.pyx @@ -0,0 +1,39 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from libc cimport stdlib + +cdef extern from "grpc/protoc/main.h": + int main(int argc, char *argv[]) + +def run_main(list args not None): + cdef char **argv = stdlib.malloc(len(args)*sizeof(char *)) + for i in range(len(args)): + argv[i] = args[i] + return main(len(args), argv) diff --git a/tools/distrib/python/grpcio_protoc/protoc_deps.py b/tools/distrib/python/grpcio_protoc/protoc_deps.py new file mode 100644 index 0000000000..5be28a77d8 --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/protoc_deps.py @@ -0,0 +1,32 @@ + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# AUTO-GENERATED BY mk_grpcio_protoc.py! +CC_FILES=['google/protobuf/compiler/main.cc', 'google/protobuf/compiler/zip_writer.cc', 'google/protobuf/compiler/subprocess.cc', 'google/protobuf/compiler/ruby/ruby_generator.cc', 'google/protobuf/compiler/python/python_generator.cc', 'google/protobuf/compiler/plugin.pb.cc', 'google/protobuf/compiler/plugin.cc', 'google/protobuf/compiler/objectivec/objectivec_primitive_field.cc', 'google/protobuf/compiler/objectivec/objectivec_oneof.cc', 'google/protobuf/compiler/objectivec/objectivec_message_field.cc', 'google/protobuf/compiler/objectivec/objectivec_message.cc', 'google/protobuf/compiler/objectivec/objectivec_map_field.cc', 'google/protobuf/compiler/objectivec/objectivec_helpers.cc', 'google/protobuf/compiler/objectivec/objectivec_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_file.cc', 'google/protobuf/compiler/objectivec/objectivec_field.cc', 'google/protobuf/compiler/objectivec/objectivec_extension.cc', 'google/protobuf/compiler/objectivec/objectivec_enum_field.cc', 'google/protobuf/compiler/objectivec/objectivec_enum.cc', 'google/protobuf/compiler/js/js_generator.cc', 'google/protobuf/compiler/javanano/javanano_primitive_field.cc', 'google/protobuf/compiler/javanano/javanano_message_field.cc', 'google/protobuf/compiler/javanano/javanano_message.cc', 'google/protobuf/compiler/javanano/javanano_map_field.cc', 'google/protobuf/compiler/javanano/javanano_helpers.cc', 'google/protobuf/compiler/javanano/javanano_generator.cc', 'google/protobuf/compiler/javanano/javanano_file.cc', 'google/protobuf/compiler/javanano/javanano_field.cc', 'google/protobuf/compiler/javanano/javanano_extension.cc', 'google/protobuf/compiler/javanano/javanano_enum_field.cc', 'google/protobuf/compiler/javanano/javanano_enum.cc', 'google/protobuf/compiler/java/java_string_field_lite.cc', 'google/protobuf/compiler/java/java_string_field.cc', 'google/protobuf/compiler/java/java_shared_code_generator.cc', 'google/protobuf/compiler/java/java_service.cc', 'google/protobuf/compiler/java/java_primitive_field_lite.cc', 'google/protobuf/compiler/java/java_primitive_field.cc', 'google/protobuf/compiler/java/java_name_resolver.cc', 'google/protobuf/compiler/java/java_message_lite.cc', 'google/protobuf/compiler/java/java_message_field_lite.cc', 'google/protobuf/compiler/java/java_message_field.cc', 'google/protobuf/compiler/java/java_message_builder_lite.cc', 'google/protobuf/compiler/java/java_message_builder.cc', 'google/protobuf/compiler/java/java_message.cc', 'google/protobuf/compiler/java/java_map_field_lite.cc', 'google/protobuf/compiler/java/java_map_field.cc', 'google/protobuf/compiler/java/java_lazy_message_field_lite.cc', 'google/protobuf/compiler/java/java_lazy_message_field.cc', 'google/protobuf/compiler/java/java_helpers.cc', 'google/protobuf/compiler/java/java_generator_factory.cc', 'google/protobuf/compiler/java/java_generator.cc', 'google/protobuf/compiler/java/java_file.cc', 'google/protobuf/compiler/java/java_field.cc', 'google/protobuf/compiler/java/java_extension.cc', 'google/protobuf/compiler/java/java_enum_lite.cc', 'google/protobuf/compiler/java/java_enum_field_lite.cc', 'google/protobuf/compiler/java/java_enum_field.cc', 'google/protobuf/compiler/java/java_enum.cc', 'google/protobuf/compiler/java/java_doc_comment.cc', 'google/protobuf/compiler/java/java_context.cc', 'google/protobuf/compiler/csharp/csharp_wrapper_field.cc', 'google/protobuf/compiler/csharp/csharp_source_generator_base.cc', 'google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_message_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_reflection_class.cc', 'google/protobuf/compiler/csharp/csharp_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_message_field.cc', 'google/protobuf/compiler/csharp/csharp_message.cc', 'google/protobuf/compiler/csharp/csharp_map_field.cc', 'google/protobuf/compiler/csharp/csharp_helpers.cc', 'google/protobuf/compiler/csharp/csharp_generator.cc', 'google/protobuf/compiler/csharp/csharp_field_base.cc', 'google/protobuf/compiler/csharp/csharp_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_enum.cc', 'google/protobuf/compiler/csharp/csharp_doc_comment.cc', 'google/protobuf/compiler/cpp/cpp_string_field.cc', 'google/protobuf/compiler/cpp/cpp_service.cc', 'google/protobuf/compiler/cpp/cpp_primitive_field.cc', 'google/protobuf/compiler/cpp/cpp_message_field.cc', 'google/protobuf/compiler/cpp/cpp_message.cc', 'google/protobuf/compiler/cpp/cpp_map_field.cc', 'google/protobuf/compiler/cpp/cpp_helpers.cc', 'google/protobuf/compiler/cpp/cpp_generator.cc', 'google/protobuf/compiler/cpp/cpp_file.cc', 'google/protobuf/compiler/cpp/cpp_field.cc', 'google/protobuf/compiler/cpp/cpp_extension.cc', 'google/protobuf/compiler/cpp/cpp_enum_field.cc', 'google/protobuf/compiler/cpp/cpp_enum.cc', 'google/protobuf/compiler/command_line_interface.cc', 'google/protobuf/compiler/code_generator.cc', 'google/protobuf/wrappers.pb.cc', 'google/protobuf/wire_format.cc', 'google/protobuf/util/type_resolver_util.cc', 'google/protobuf/util/time_util.cc', 'google/protobuf/util/message_differencer.cc', 'google/protobuf/util/json_util.cc', 'google/protobuf/util/internal/utility.cc', 'google/protobuf/util/internal/type_info_test_helper.cc', 'google/protobuf/util/internal/type_info.cc', 'google/protobuf/util/internal/protostream_objectwriter.cc', 'google/protobuf/util/internal/protostream_objectsource.cc', 'google/protobuf/util/internal/proto_writer.cc', 'google/protobuf/util/internal/object_writer.cc', 'google/protobuf/util/internal/json_stream_parser.cc', 'google/protobuf/util/internal/json_objectwriter.cc', 'google/protobuf/util/internal/json_escaping.cc', 'google/protobuf/util/internal/field_mask_utility.cc', 'google/protobuf/util/internal/error_listener.cc', 'google/protobuf/util/internal/default_value_objectwriter.cc', 'google/protobuf/util/internal/datapiece.cc', 'google/protobuf/util/field_mask_util.cc', 'google/protobuf/util/field_comparator.cc', 'google/protobuf/unknown_field_set.cc', 'google/protobuf/type.pb.cc', 'google/protobuf/timestamp.pb.cc', 'google/protobuf/text_format.cc', 'google/protobuf/stubs/substitute.cc', 'google/protobuf/stubs/mathlimits.cc', 'google/protobuf/struct.pb.cc', 'google/protobuf/source_context.pb.cc', 'google/protobuf/service.cc', 'google/protobuf/reflection_ops.cc', 'google/protobuf/message.cc', 'google/protobuf/map_field.cc', 'google/protobuf/io/zero_copy_stream_impl.cc', 'google/protobuf/io/tokenizer.cc', 'google/protobuf/io/strtod.cc', 'google/protobuf/io/printer.cc', 'google/protobuf/io/gzip_stream.cc', 'google/protobuf/generated_message_reflection.cc', 'google/protobuf/field_mask.pb.cc', 'google/protobuf/extension_set_heavy.cc', 'google/protobuf/empty.pb.cc', 'google/protobuf/dynamic_message.cc', 'google/protobuf/duration.pb.cc', 'google/protobuf/descriptor_database.cc', 'google/protobuf/descriptor.pb.cc', 'google/protobuf/descriptor.cc', 'google/protobuf/compiler/parser.cc', 'google/protobuf/compiler/importer.cc', 'google/protobuf/api.pb.cc', 'google/protobuf/any.pb.cc', 'google/protobuf/any.cc', 'google/protobuf/wire_format_lite.cc', 'google/protobuf/stubs/time.cc', 'google/protobuf/stubs/strutil.cc', 'google/protobuf/stubs/structurally_valid.cc', 'google/protobuf/stubs/stringprintf.cc', 'google/protobuf/stubs/stringpiece.cc', 'google/protobuf/stubs/statusor.cc', 'google/protobuf/stubs/status.cc', 'google/protobuf/stubs/once.cc', 'google/protobuf/stubs/int128.cc', 'google/protobuf/stubs/common.cc', 'google/protobuf/stubs/bytestream.cc', 'google/protobuf/stubs/atomicops_internals_x86_msvc.cc', 'google/protobuf/stubs/atomicops_internals_x86_gcc.cc', 'google/protobuf/repeated_field.cc', 'google/protobuf/message_lite.cc', 'google/protobuf/io/zero_copy_stream_impl_lite.cc', 'google/protobuf/io/zero_copy_stream.cc', 'google/protobuf/io/coded_stream.cc', 'google/protobuf/generated_message_util.cc', 'google/protobuf/extension_set.cc', 'google/protobuf/arenastring.cc', 'google/protobuf/arena.cc'] diff --git a/tools/distrib/python/grpcio_protoc/protoc_lib_deps.py b/tools/distrib/python/grpcio_protoc/protoc_lib_deps.py new file mode 100644 index 0000000000..00a8f31069 --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/protoc_lib_deps.py @@ -0,0 +1,32 @@ + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# AUTO-GENERATED BY mk_grpcio_protoc.py! +CC_FILES=['google/protobuf/compiler/zip_writer.cc', 'google/protobuf/compiler/subprocess.cc', 'google/protobuf/compiler/ruby/ruby_generator.cc', 'google/protobuf/compiler/python/python_generator.cc', 'google/protobuf/compiler/plugin.pb.cc', 'google/protobuf/compiler/plugin.cc', 'google/protobuf/compiler/objectivec/objectivec_primitive_field.cc', 'google/protobuf/compiler/objectivec/objectivec_oneof.cc', 'google/protobuf/compiler/objectivec/objectivec_message_field.cc', 'google/protobuf/compiler/objectivec/objectivec_message.cc', 'google/protobuf/compiler/objectivec/objectivec_map_field.cc', 'google/protobuf/compiler/objectivec/objectivec_helpers.cc', 'google/protobuf/compiler/objectivec/objectivec_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_file.cc', 'google/protobuf/compiler/objectivec/objectivec_field.cc', 'google/protobuf/compiler/objectivec/objectivec_extension.cc', 'google/protobuf/compiler/objectivec/objectivec_enum_field.cc', 'google/protobuf/compiler/objectivec/objectivec_enum.cc', 'google/protobuf/compiler/js/js_generator.cc', 'google/protobuf/compiler/javanano/javanano_primitive_field.cc', 'google/protobuf/compiler/javanano/javanano_message_field.cc', 'google/protobuf/compiler/javanano/javanano_message.cc', 'google/protobuf/compiler/javanano/javanano_map_field.cc', 'google/protobuf/compiler/javanano/javanano_helpers.cc', 'google/protobuf/compiler/javanano/javanano_generator.cc', 'google/protobuf/compiler/javanano/javanano_file.cc', 'google/protobuf/compiler/javanano/javanano_field.cc', 'google/protobuf/compiler/javanano/javanano_extension.cc', 'google/protobuf/compiler/javanano/javanano_enum_field.cc', 'google/protobuf/compiler/javanano/javanano_enum.cc', 'google/protobuf/compiler/java/java_string_field_lite.cc', 'google/protobuf/compiler/java/java_string_field.cc', 'google/protobuf/compiler/java/java_shared_code_generator.cc', 'google/protobuf/compiler/java/java_service.cc', 'google/protobuf/compiler/java/java_primitive_field_lite.cc', 'google/protobuf/compiler/java/java_primitive_field.cc', 'google/protobuf/compiler/java/java_name_resolver.cc', 'google/protobuf/compiler/java/java_message_lite.cc', 'google/protobuf/compiler/java/java_message_field_lite.cc', 'google/protobuf/compiler/java/java_message_field.cc', 'google/protobuf/compiler/java/java_message_builder_lite.cc', 'google/protobuf/compiler/java/java_message_builder.cc', 'google/protobuf/compiler/java/java_message.cc', 'google/protobuf/compiler/java/java_map_field_lite.cc', 'google/protobuf/compiler/java/java_map_field.cc', 'google/protobuf/compiler/java/java_lazy_message_field_lite.cc', 'google/protobuf/compiler/java/java_lazy_message_field.cc', 'google/protobuf/compiler/java/java_helpers.cc', 'google/protobuf/compiler/java/java_generator_factory.cc', 'google/protobuf/compiler/java/java_generator.cc', 'google/protobuf/compiler/java/java_file.cc', 'google/protobuf/compiler/java/java_field.cc', 'google/protobuf/compiler/java/java_extension.cc', 'google/protobuf/compiler/java/java_enum_lite.cc', 'google/protobuf/compiler/java/java_enum_field_lite.cc', 'google/protobuf/compiler/java/java_enum_field.cc', 'google/protobuf/compiler/java/java_enum.cc', 'google/protobuf/compiler/java/java_doc_comment.cc', 'google/protobuf/compiler/java/java_context.cc', 'google/protobuf/compiler/csharp/csharp_wrapper_field.cc', 'google/protobuf/compiler/csharp/csharp_source_generator_base.cc', 'google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_message_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_reflection_class.cc', 'google/protobuf/compiler/csharp/csharp_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_message_field.cc', 'google/protobuf/compiler/csharp/csharp_message.cc', 'google/protobuf/compiler/csharp/csharp_map_field.cc', 'google/protobuf/compiler/csharp/csharp_helpers.cc', 'google/protobuf/compiler/csharp/csharp_generator.cc', 'google/protobuf/compiler/csharp/csharp_field_base.cc', 'google/protobuf/compiler/csharp/csharp_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_enum.cc', 'google/protobuf/compiler/csharp/csharp_doc_comment.cc', 'google/protobuf/compiler/cpp/cpp_string_field.cc', 'google/protobuf/compiler/cpp/cpp_service.cc', 'google/protobuf/compiler/cpp/cpp_primitive_field.cc', 'google/protobuf/compiler/cpp/cpp_message_field.cc', 'google/protobuf/compiler/cpp/cpp_message.cc', 'google/protobuf/compiler/cpp/cpp_map_field.cc', 'google/protobuf/compiler/cpp/cpp_helpers.cc', 'google/protobuf/compiler/cpp/cpp_generator.cc', 'google/protobuf/compiler/cpp/cpp_file.cc', 'google/protobuf/compiler/cpp/cpp_field.cc', 'google/protobuf/compiler/cpp/cpp_extension.cc', 'google/protobuf/compiler/cpp/cpp_enum_field.cc', 'google/protobuf/compiler/cpp/cpp_enum.cc', 'google/protobuf/compiler/command_line_interface.cc', 'google/protobuf/compiler/code_generator.cc', 'google/protobuf/wrappers.pb.cc', 'google/protobuf/wire_format.cc', 'google/protobuf/util/type_resolver_util.cc', 'google/protobuf/util/time_util.cc', 'google/protobuf/util/message_differencer.cc', 'google/protobuf/util/json_util.cc', 'google/protobuf/util/internal/utility.cc', 'google/protobuf/util/internal/type_info_test_helper.cc', 'google/protobuf/util/internal/type_info.cc', 'google/protobuf/util/internal/protostream_objectwriter.cc', 'google/protobuf/util/internal/protostream_objectsource.cc', 'google/protobuf/util/internal/proto_writer.cc', 'google/protobuf/util/internal/object_writer.cc', 'google/protobuf/util/internal/json_stream_parser.cc', 'google/protobuf/util/internal/json_objectwriter.cc', 'google/protobuf/util/internal/json_escaping.cc', 'google/protobuf/util/internal/field_mask_utility.cc', 'google/protobuf/util/internal/error_listener.cc', 'google/protobuf/util/internal/default_value_objectwriter.cc', 'google/protobuf/util/internal/datapiece.cc', 'google/protobuf/util/field_mask_util.cc', 'google/protobuf/util/field_comparator.cc', 'google/protobuf/unknown_field_set.cc', 'google/protobuf/type.pb.cc', 'google/protobuf/timestamp.pb.cc', 'google/protobuf/text_format.cc', 'google/protobuf/stubs/substitute.cc', 'google/protobuf/stubs/mathlimits.cc', 'google/protobuf/struct.pb.cc', 'google/protobuf/source_context.pb.cc', 'google/protobuf/service.cc', 'google/protobuf/reflection_ops.cc', 'google/protobuf/message.cc', 'google/protobuf/map_field.cc', 'google/protobuf/io/zero_copy_stream_impl.cc', 'google/protobuf/io/tokenizer.cc', 'google/protobuf/io/strtod.cc', 'google/protobuf/io/printer.cc', 'google/protobuf/io/gzip_stream.cc', 'google/protobuf/generated_message_reflection.cc', 'google/protobuf/field_mask.pb.cc', 'google/protobuf/extension_set_heavy.cc', 'google/protobuf/empty.pb.cc', 'google/protobuf/dynamic_message.cc', 'google/protobuf/duration.pb.cc', 'google/protobuf/descriptor_database.cc', 'google/protobuf/descriptor.pb.cc', 'google/protobuf/descriptor.cc', 'google/protobuf/compiler/parser.cc', 'google/protobuf/compiler/importer.cc', 'google/protobuf/api.pb.cc', 'google/protobuf/any.pb.cc', 'google/protobuf/any.cc', 'google/protobuf/wire_format_lite.cc', 'google/protobuf/stubs/time.cc', 'google/protobuf/stubs/strutil.cc', 'google/protobuf/stubs/structurally_valid.cc', 'google/protobuf/stubs/stringprintf.cc', 'google/protobuf/stubs/stringpiece.cc', 'google/protobuf/stubs/statusor.cc', 'google/protobuf/stubs/status.cc', 'google/protobuf/stubs/once.cc', 'google/protobuf/stubs/int128.cc', 'google/protobuf/stubs/common.cc', 'google/protobuf/stubs/bytestream.cc', 'google/protobuf/stubs/atomicops_internals_x86_msvc.cc', 'google/protobuf/stubs/atomicops_internals_x86_gcc.cc', 'google/protobuf/repeated_field.cc', 'google/protobuf/message_lite.cc', 'google/protobuf/io/zero_copy_stream_impl_lite.cc', 'google/protobuf/io/zero_copy_stream.cc', 'google/protobuf/io/coded_stream.cc', 'google/protobuf/generated_message_util.cc', 'google/protobuf/extension_set.cc', 'google/protobuf/arenastring.cc', 'google/protobuf/arena.cc'] diff --git a/tools/distrib/python/grpcio_protoc/setup.py b/tools/distrib/python/grpcio_protoc/setup.py new file mode 100644 index 0000000000..d462b6b213 --- /dev/null +++ b/tools/distrib/python/grpcio_protoc/setup.py @@ -0,0 +1,102 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from distutils import extension +import os +import os.path +import sys + +import setuptools +from setuptools.command import build_ext + +# TODO(atash) add flag to disable Cython use + +os.chdir(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, os.path.abspath('.')) + +import protoc_deps +import protoc_lib_deps + +def protoc_ext_module(): + protoc_sources = [ + os.path.join('third_party/protobuf/src', cc_file) + for cc_file in protoc_deps.CC_FILES] + protoc_ext = extension.Extension( + name='grpc.protoc.protoc', + sources=['grpc/protoc/protoc.pyx'] + protoc_sources, + include_dirs=['.', 'third_party/protobuf/src'], + language='c++', + define_macros=[('HAVE_PTHREAD', 1)], + extra_compile_args=['-lpthread', '-frtti'], + ) + return protoc_ext + +def plugin_ext_module(): + plugin_sources = [ + 'grpc_root/src/compiler/python_generator.cc', + 'grpc_root/src/compiler/python_plugin.cc'] + [ + os.path.join('third_party/protobuf/src', cc_file) + for cc_file in protoc_lib_deps.CC_FILES] + plugin_ext = extension.Extension( + name='grpc.protoc.protoc_plugin', + sources=['grpc/protoc/protoc_plugin.pyx'] + plugin_sources, + include_dirs=[ + '.', + 'grpc_root', + 'grpc_root/include', + 'third_party/protobuf/src', + ], + language='c++', + define_macros=[('HAVE_PTHREAD', 1)], + extra_compile_args=['-lpthread', '-std=c++11'], + ) + return plugin_ext + +def maybe_cythonize(exts): + from Cython import Build + return Build.cythonize(exts) + +setuptools.setup( + name='grpcio_protoc', + version='0.14.0rc1', + license='', + ext_modules=maybe_cythonize([ + protoc_ext_module(), + plugin_ext_module(), + ]), + scripts=[ + 'grpc/protoc/grpc_python_protoc_compiler.py', + 'grpc/protoc/grpc_python_protoc_plugin.py', + ], + packages=setuptools.find_packages('.'), + namespace_packages=['grpc'], + install_requires=[ + 'protobuf>=3.0.0a3', + ], +) diff --git a/tools/distrib/python/grpcio_tools/MANIFEST.in b/tools/distrib/python/grpcio_tools/MANIFEST.in new file mode 100644 index 0000000000..e6ab312f09 --- /dev/null +++ b/tools/distrib/python/grpcio_tools/MANIFEST.in @@ -0,0 +1,5 @@ +include protoc_deps.py +include protoc_lib_deps.py +graft grpc +graft grpc_root +graft third_party diff --git a/tools/distrib/python/mk_grpcio_protoc.py b/tools/distrib/python/mk_grpcio_protoc.py new file mode 100755 index 0000000000..c09a77982d --- /dev/null +++ b/tools/distrib/python/mk_grpcio_protoc.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import os.path +import shutil +import subprocess + +DEPS_FILE_CONTENT=""" +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# AUTO-GENERATED BY mk_grpcio_protoc.py! +CC_FILES={} +""" + +# Bazel query result prefix for expected source files in protobuf. +PROTOBUF_CC_PREFIX = '//:src/' + +os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)), + '..', '..', '..')) + +GRPC_PYTHON_ROOT = os.path.abspath('tools/distrib/python/grpcio_protoc') + +GRPC_PROTOBUF = os.path.abspath('third_party/protobuf/src') +GRPC_PROTOC_PLUGINS = os.path.abspath('src/compiler') +GRPC_PYTHON_PROTOBUF = os.path.join(GRPC_PYTHON_ROOT, + 'third_party/protobuf/src') +GRPC_PYTHON_PROTOC_PLUGINS = os.path.join(GRPC_PYTHON_ROOT, + 'grpc_root/src/compiler') +GRPC_PYTHON_PROTOC_DEPS = os.path.join(GRPC_PYTHON_ROOT, + 'protoc_deps.py') +GRPC_PYTHON_PROTOC_LIB_DEPS = os.path.join(GRPC_PYTHON_ROOT, + 'protoc_lib_deps.py') + +GRPC_INCLUDE = os.path.abspath('include') +GRPC_PYTHON_INCLUDE = os.path.join(GRPC_PYTHON_ROOT, 'grpc_root/include') + +for tree in [GRPC_PYTHON_PROTOBUF, + GRPC_PYTHON_PROTOC_PLUGINS, + GRPC_PYTHON_INCLUDE]: + try: + shutil.rmtree(tree) + except Exception as _: + pass +shutil.copytree(GRPC_PROTOBUF, GRPC_PYTHON_PROTOBUF) +shutil.copytree(GRPC_PROTOC_PLUGINS, GRPC_PYTHON_PROTOC_PLUGINS) +shutil.copytree(GRPC_INCLUDE, GRPC_PYTHON_INCLUDE) + +def write_deps(query, out_filename): + output = subprocess.check_output(['tools/distrib/python/bazel_deps.sh', query]) + output = output.splitlines() + cc_files = [ + name for name in output + if name.endswith('.cc') and name.startswith(PROTOBUF_CC_PREFIX)] + cc_files = [cc_file[len(PROTOBUF_CC_PREFIX):] for cc_file in cc_files] + + deps_file_content = DEPS_FILE_CONTENT.format(cc_files) + + with open(out_filename, 'w') as deps_file: + deps_file.write(deps_file_content) + +write_deps('//:protoc', GRPC_PYTHON_PROTOC_DEPS) +write_deps('//:protoc_lib', GRPC_PYTHON_PROTOC_LIB_DEPS) diff --git a/tools/dockerfile/bazel/Dockerfile b/tools/dockerfile/bazel/Dockerfile new file mode 100644 index 0000000000..af31adb94d --- /dev/null +++ b/tools/dockerfile/bazel/Dockerfile @@ -0,0 +1,53 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +FROM ubuntu:wily +RUN apt-get update +RUN apt-get -y install software-properties-common python-software-properties +RUN add-apt-repository ppa:webupd8team/java +RUN apt-get update +RUN apt-get -y install \ + vim \ + wget \ + openjdk-8-jdk \ + pkg-config \ + zip \ + g++ \ + zlib1g-dev \ + unzip \ + git + +RUN git clone https://github.com/bazelbuild/bazel.git /bazel +RUN cd /bazel && \ + ./compile.sh + +RUN cp /bazel/output/bazel /bin/bazel + +# ensure the installation has been extracted +RUN bazel -- cgit v1.2.3 From 8ca294e417217e1577609052f18df84be437c03c Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Mon, 2 May 2016 14:56:30 -0700 Subject: Refactoring the core security code. As opposed to a flat directory, we now have the following structure: - security -context - credentials - composite - fake - google_default - iam - jwt - oauth2 - plugin - ssl - transport - util We have not refactored the test code yet but this PR is already large enough... --- BUILD | 126 +- Makefile | 72 +- binding.gyp | 36 +- build.yaml | 63 +- config.m4 | 49 +- gRPC.podspec | 90 +- grpc.gemspec | 63 +- package.xml | 63 +- .../chttp2/client/secure/secure_channel_create.c | 6 +- .../chttp2/server/secure/server_secure_chttp2.c | 8 +- src/core/lib/http/httpcli_security_connector.c | 2 +- src/core/lib/security/auth_filters.h | 42 - src/core/lib/security/b64.c | 233 ---- src/core/lib/security/b64.h | 52 - src/core/lib/security/client_auth_filter.c | 336 ----- src/core/lib/security/context/security_context.c | 347 ++++++ src/core/lib/security/context/security_context.h | 114 ++ src/core/lib/security/credentials.c | 1296 -------------------- src/core/lib/security/credentials.h | 377 ------ .../credentials/composite/composite_credentials.c | 263 ++++ .../credentials/composite/composite_credentials.h | 72 ++ src/core/lib/security/credentials/credentials.c | 233 ++++ src/core/lib/security/credentials/credentials.h | 236 ++++ .../security/credentials/credentials_metadata.c | 101 ++ .../security/credentials/fake/fake_credentials.c | 139 +++ .../security/credentials/fake/fake_credentials.h | 56 + .../credentials/google_default/credentials_posix.c | 61 + .../credentials/google_default/credentials_win32.c | 61 + .../google_default/google_default_credentials.c | 268 ++++ .../google_default/google_default_credentials.h | 47 + .../lib/security/credentials/iam/iam_credentials.c | 87 ++ .../lib/security/credentials/iam/iam_credentials.h | 47 + src/core/lib/security/credentials/jwt/json_token.c | 321 +++++ src/core/lib/security/credentials/jwt/json_token.h | 88 ++ .../lib/security/credentials/jwt/jwt_credentials.c | 161 +++ .../lib/security/credentials/jwt/jwt_credentials.h | 63 + .../lib/security/credentials/jwt/jwt_verifier.c | 843 +++++++++++++ .../lib/security/credentials/jwt/jwt_verifier.h | 136 ++ .../credentials/oauth2/oauth2_credentials.c | 430 +++++++ .../credentials/oauth2/oauth2_credentials.h | 111 ++ .../credentials/plugin/plugin_credentials.c | 131 ++ .../credentials/plugin/plugin_credentials.h | 48 + .../lib/security/credentials/ssl/ssl_credentials.c | 244 ++++ .../lib/security/credentials/ssl/ssl_credentials.h | 49 + src/core/lib/security/credentials_metadata.c | 101 -- src/core/lib/security/credentials_posix.c | 61 - src/core/lib/security/credentials_win32.c | 61 - src/core/lib/security/google_default_credentials.c | 266 ---- src/core/lib/security/handshake.c | 336 ----- src/core/lib/security/handshake.h | 51 - src/core/lib/security/json_token.c | 411 ------- src/core/lib/security/json_token.h | 118 -- src/core/lib/security/jwt_verifier.c | 843 ------------- src/core/lib/security/jwt_verifier.h | 136 -- src/core/lib/security/secure_endpoint.c | 384 ------ src/core/lib/security/secure_endpoint.h | 49 - src/core/lib/security/security_connector.c | 838 ------------- src/core/lib/security/security_connector.h | 266 ---- src/core/lib/security/security_context.c | 347 ------ src/core/lib/security/security_context.h | 114 -- src/core/lib/security/server_auth_filter.c | 264 ---- src/core/lib/security/transport/auth_filters.h | 42 + .../lib/security/transport/client_auth_filter.c | 336 +++++ src/core/lib/security/transport/handshake.c | 336 +++++ src/core/lib/security/transport/handshake.h | 51 + src/core/lib/security/transport/secure_endpoint.c | 384 ++++++ src/core/lib/security/transport/secure_endpoint.h | 49 + .../lib/security/transport/security_connector.c | 838 +++++++++++++ .../lib/security/transport/security_connector.h | 266 ++++ .../lib/security/transport/server_auth_filter.c | 264 ++++ src/core/lib/security/util/b64.c | 233 ++++ src/core/lib/security/util/b64.h | 52 + src/core/lib/security/util/json_util.c | 62 + src/core/lib/security/util/json_util.h | 57 + src/core/lib/surface/init_secure.c | 8 +- src/python/grpcio/grpc_core_dependencies.py | 36 +- .../set_initial_connect_string_test.c | 2 +- test/core/end2end/fixtures/h2_fakesec.c | 2 +- test/core/end2end/fixtures/h2_oauth2.c | 2 +- test/core/end2end/fixtures/h2_ssl.c | 2 +- test/core/end2end/fixtures/h2_ssl_cert.c | 2 +- test/core/end2end/fixtures/h2_ssl_proxy.c | 2 +- test/core/end2end/tests/call_creds.c | 2 +- test/core/security/auth_context_test.c | 2 +- test/core/security/b64_test.c | 2 +- test/core/security/create_jwt.c | 3 +- test/core/security/credentials_test.c | 7 +- test/core/security/fetch_oauth2.c | 2 +- test/core/security/json_token_test.c | 5 +- test/core/security/jwt_verifier_test.c | 6 +- test/core/security/oauth2_utils.c | 2 +- test/core/security/oauth2_utils.h | 2 +- .../security/print_google_default_creds_token.c | 3 +- test/core/security/secure_endpoint_test.c | 2 +- test/core/security/security_connector_test.c | 4 +- test/core/security/verify_jwt.c | 2 +- test/core/surface/secure_channel_create_test.c | 4 +- test/core/surface/server_chttp2_test.c | 3 +- test/cpp/common/auth_property_iterator_test.cc | 2 +- test/cpp/common/secure_auth_context_test.cc | 2 +- test/cpp/end2end/end2end_test.cc | 2 +- tools/doxygen/Doxyfile.core.internal | 63 +- tools/run_tests/sources_and_headers.json | 90 +- vsprojects/vcxproj/grpc/grpc.vcxproj | 71 +- vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 179 ++- 105 files changed, 8435 insertions(+), 7368 deletions(-) delete mode 100644 src/core/lib/security/auth_filters.h delete mode 100644 src/core/lib/security/b64.c delete mode 100644 src/core/lib/security/b64.h delete mode 100644 src/core/lib/security/client_auth_filter.c create mode 100644 src/core/lib/security/context/security_context.c create mode 100644 src/core/lib/security/context/security_context.h delete mode 100644 src/core/lib/security/credentials.c delete mode 100644 src/core/lib/security/credentials.h create mode 100644 src/core/lib/security/credentials/composite/composite_credentials.c create mode 100644 src/core/lib/security/credentials/composite/composite_credentials.h create mode 100644 src/core/lib/security/credentials/credentials.c create mode 100644 src/core/lib/security/credentials/credentials.h create mode 100644 src/core/lib/security/credentials/credentials_metadata.c create mode 100644 src/core/lib/security/credentials/fake/fake_credentials.c create mode 100644 src/core/lib/security/credentials/fake/fake_credentials.h create mode 100644 src/core/lib/security/credentials/google_default/credentials_posix.c create mode 100644 src/core/lib/security/credentials/google_default/credentials_win32.c create mode 100644 src/core/lib/security/credentials/google_default/google_default_credentials.c create mode 100644 src/core/lib/security/credentials/google_default/google_default_credentials.h create mode 100644 src/core/lib/security/credentials/iam/iam_credentials.c create mode 100644 src/core/lib/security/credentials/iam/iam_credentials.h create mode 100644 src/core/lib/security/credentials/jwt/json_token.c create mode 100644 src/core/lib/security/credentials/jwt/json_token.h create mode 100644 src/core/lib/security/credentials/jwt/jwt_credentials.c create mode 100644 src/core/lib/security/credentials/jwt/jwt_credentials.h create mode 100644 src/core/lib/security/credentials/jwt/jwt_verifier.c create mode 100644 src/core/lib/security/credentials/jwt/jwt_verifier.h create mode 100644 src/core/lib/security/credentials/oauth2/oauth2_credentials.c create mode 100644 src/core/lib/security/credentials/oauth2/oauth2_credentials.h create mode 100644 src/core/lib/security/credentials/plugin/plugin_credentials.c create mode 100644 src/core/lib/security/credentials/plugin/plugin_credentials.h create mode 100644 src/core/lib/security/credentials/ssl/ssl_credentials.c create mode 100644 src/core/lib/security/credentials/ssl/ssl_credentials.h delete mode 100644 src/core/lib/security/credentials_metadata.c delete mode 100644 src/core/lib/security/credentials_posix.c delete mode 100644 src/core/lib/security/credentials_win32.c delete mode 100644 src/core/lib/security/google_default_credentials.c delete mode 100644 src/core/lib/security/handshake.c delete mode 100644 src/core/lib/security/handshake.h delete mode 100644 src/core/lib/security/json_token.c delete mode 100644 src/core/lib/security/json_token.h delete mode 100644 src/core/lib/security/jwt_verifier.c delete mode 100644 src/core/lib/security/jwt_verifier.h delete mode 100644 src/core/lib/security/secure_endpoint.c delete mode 100644 src/core/lib/security/secure_endpoint.h delete mode 100644 src/core/lib/security/security_connector.c delete mode 100644 src/core/lib/security/security_connector.h delete mode 100644 src/core/lib/security/security_context.c delete mode 100644 src/core/lib/security/security_context.h delete mode 100644 src/core/lib/security/server_auth_filter.c create mode 100644 src/core/lib/security/transport/auth_filters.h create mode 100644 src/core/lib/security/transport/client_auth_filter.c create mode 100644 src/core/lib/security/transport/handshake.c create mode 100644 src/core/lib/security/transport/handshake.h create mode 100644 src/core/lib/security/transport/secure_endpoint.c create mode 100644 src/core/lib/security/transport/secure_endpoint.h create mode 100644 src/core/lib/security/transport/security_connector.c create mode 100644 src/core/lib/security/transport/security_connector.h create mode 100644 src/core/lib/security/transport/server_auth_filter.c create mode 100644 src/core/lib/security/util/b64.c create mode 100644 src/core/lib/security/util/b64.h create mode 100644 src/core/lib/security/util/json_util.c create mode 100644 src/core/lib/security/util/json_util.h (limited to 'src/python/grpcio') diff --git a/BUILD b/BUILD index b4b10b535e..ac16f07cd0 100644 --- a/BUILD +++ b/BUILD @@ -255,15 +255,24 @@ cc_library( "src/core/ext/transport/chttp2/transport/timeout_encoding.h", "src/core/ext/transport/chttp2/transport/varint.h", "src/core/ext/transport/chttp2/alpn/alpn.h", - "src/core/lib/security/auth_filters.h", - "src/core/lib/security/b64.h", - "src/core/lib/security/credentials.h", - "src/core/lib/security/handshake.h", - "src/core/lib/security/json_token.h", - "src/core/lib/security/jwt_verifier.h", - "src/core/lib/security/secure_endpoint.h", - "src/core/lib/security/security_connector.h", - "src/core/lib/security/security_context.h", + "src/core/lib/security/context/security_context.h", + "src/core/lib/security/credentials/composite/composite_credentials.h", + "src/core/lib/security/credentials/credentials.h", + "src/core/lib/security/credentials/fake/fake_credentials.h", + "src/core/lib/security/credentials/google_default/google_default_credentials.h", + "src/core/lib/security/credentials/iam/iam_credentials.h", + "src/core/lib/security/credentials/jwt/json_token.h", + "src/core/lib/security/credentials/jwt/jwt_credentials.h", + "src/core/lib/security/credentials/jwt/jwt_verifier.h", + "src/core/lib/security/credentials/oauth2/oauth2_credentials.h", + "src/core/lib/security/credentials/plugin/plugin_credentials.h", + "src/core/lib/security/credentials/ssl/ssl_credentials.h", + "src/core/lib/security/transport/auth_filters.h", + "src/core/lib/security/transport/handshake.h", + "src/core/lib/security/transport/secure_endpoint.h", + "src/core/lib/security/transport/security_connector.h", + "src/core/lib/security/util/b64.h", + "src/core/lib/security/util/json_util.h", "src/core/lib/tsi/fake_transport_security.h", "src/core/lib/tsi/ssl_transport_security.h", "src/core/lib/tsi/ssl_types.h", @@ -399,20 +408,28 @@ cc_library( "src/core/ext/transport/chttp2/transport/writing.c", "src/core/ext/transport/chttp2/alpn/alpn.c", "src/core/lib/http/httpcli_security_connector.c", - "src/core/lib/security/b64.c", - "src/core/lib/security/client_auth_filter.c", - "src/core/lib/security/credentials.c", - "src/core/lib/security/credentials_metadata.c", - "src/core/lib/security/credentials_posix.c", - "src/core/lib/security/credentials_win32.c", - "src/core/lib/security/google_default_credentials.c", - "src/core/lib/security/handshake.c", - "src/core/lib/security/json_token.c", - "src/core/lib/security/jwt_verifier.c", - "src/core/lib/security/secure_endpoint.c", - "src/core/lib/security/security_connector.c", - "src/core/lib/security/security_context.c", - "src/core/lib/security/server_auth_filter.c", + "src/core/lib/security/context/security_context.c", + "src/core/lib/security/credentials/composite/composite_credentials.c", + "src/core/lib/security/credentials/credentials.c", + "src/core/lib/security/credentials/credentials_metadata.c", + "src/core/lib/security/credentials/fake/fake_credentials.c", + "src/core/lib/security/credentials/google_default/credentials_posix.c", + "src/core/lib/security/credentials/google_default/credentials_win32.c", + "src/core/lib/security/credentials/google_default/google_default_credentials.c", + "src/core/lib/security/credentials/iam/iam_credentials.c", + "src/core/lib/security/credentials/jwt/json_token.c", + "src/core/lib/security/credentials/jwt/jwt_credentials.c", + "src/core/lib/security/credentials/jwt/jwt_verifier.c", + "src/core/lib/security/credentials/oauth2/oauth2_credentials.c", + "src/core/lib/security/credentials/plugin/plugin_credentials.c", + "src/core/lib/security/credentials/ssl/ssl_credentials.c", + "src/core/lib/security/transport/client_auth_filter.c", + "src/core/lib/security/transport/handshake.c", + "src/core/lib/security/transport/secure_endpoint.c", + "src/core/lib/security/transport/security_connector.c", + "src/core/lib/security/transport/server_auth_filter.c", + "src/core/lib/security/util/b64.c", + "src/core/lib/security/util/json_util.c", "src/core/lib/surface/init_secure.c", "src/core/lib/tsi/fake_transport_security.c", "src/core/lib/tsi/ssl_transport_security.c", @@ -1416,20 +1433,28 @@ objc_library( "src/core/ext/transport/chttp2/transport/writing.c", "src/core/ext/transport/chttp2/alpn/alpn.c", "src/core/lib/http/httpcli_security_connector.c", - "src/core/lib/security/b64.c", - "src/core/lib/security/client_auth_filter.c", - "src/core/lib/security/credentials.c", - "src/core/lib/security/credentials_metadata.c", - "src/core/lib/security/credentials_posix.c", - "src/core/lib/security/credentials_win32.c", - "src/core/lib/security/google_default_credentials.c", - "src/core/lib/security/handshake.c", - "src/core/lib/security/json_token.c", - "src/core/lib/security/jwt_verifier.c", - "src/core/lib/security/secure_endpoint.c", - "src/core/lib/security/security_connector.c", - "src/core/lib/security/security_context.c", - "src/core/lib/security/server_auth_filter.c", + "src/core/lib/security/context/security_context.c", + "src/core/lib/security/credentials/composite/composite_credentials.c", + "src/core/lib/security/credentials/credentials.c", + "src/core/lib/security/credentials/credentials_metadata.c", + "src/core/lib/security/credentials/fake/fake_credentials.c", + "src/core/lib/security/credentials/google_default/credentials_posix.c", + "src/core/lib/security/credentials/google_default/credentials_win32.c", + "src/core/lib/security/credentials/google_default/google_default_credentials.c", + "src/core/lib/security/credentials/iam/iam_credentials.c", + "src/core/lib/security/credentials/jwt/json_token.c", + "src/core/lib/security/credentials/jwt/jwt_credentials.c", + "src/core/lib/security/credentials/jwt/jwt_verifier.c", + "src/core/lib/security/credentials/oauth2/oauth2_credentials.c", + "src/core/lib/security/credentials/plugin/plugin_credentials.c", + "src/core/lib/security/credentials/ssl/ssl_credentials.c", + "src/core/lib/security/transport/client_auth_filter.c", + "src/core/lib/security/transport/handshake.c", + "src/core/lib/security/transport/secure_endpoint.c", + "src/core/lib/security/transport/security_connector.c", + "src/core/lib/security/transport/server_auth_filter.c", + "src/core/lib/security/util/b64.c", + "src/core/lib/security/util/json_util.c", "src/core/lib/surface/init_secure.c", "src/core/lib/tsi/fake_transport_security.c", "src/core/lib/tsi/ssl_transport_security.c", @@ -1596,15 +1621,24 @@ objc_library( "src/core/ext/transport/chttp2/transport/timeout_encoding.h", "src/core/ext/transport/chttp2/transport/varint.h", "src/core/ext/transport/chttp2/alpn/alpn.h", - "src/core/lib/security/auth_filters.h", - "src/core/lib/security/b64.h", - "src/core/lib/security/credentials.h", - "src/core/lib/security/handshake.h", - "src/core/lib/security/json_token.h", - "src/core/lib/security/jwt_verifier.h", - "src/core/lib/security/secure_endpoint.h", - "src/core/lib/security/security_connector.h", - "src/core/lib/security/security_context.h", + "src/core/lib/security/context/security_context.h", + "src/core/lib/security/credentials/composite/composite_credentials.h", + "src/core/lib/security/credentials/credentials.h", + "src/core/lib/security/credentials/fake/fake_credentials.h", + "src/core/lib/security/credentials/google_default/google_default_credentials.h", + "src/core/lib/security/credentials/iam/iam_credentials.h", + "src/core/lib/security/credentials/jwt/json_token.h", + "src/core/lib/security/credentials/jwt/jwt_credentials.h", + "src/core/lib/security/credentials/jwt/jwt_verifier.h", + "src/core/lib/security/credentials/oauth2/oauth2_credentials.h", + "src/core/lib/security/credentials/plugin/plugin_credentials.h", + "src/core/lib/security/credentials/ssl/ssl_credentials.h", + "src/core/lib/security/transport/auth_filters.h", + "src/core/lib/security/transport/handshake.h", + "src/core/lib/security/transport/secure_endpoint.h", + "src/core/lib/security/transport/security_connector.h", + "src/core/lib/security/util/b64.h", + "src/core/lib/security/util/json_util.h", "src/core/lib/tsi/fake_transport_security.h", "src/core/lib/tsi/ssl_transport_security.h", "src/core/lib/tsi/ssl_types.h", diff --git a/Makefile b/Makefile index 922e0b0568..64ecf38f49 100644 --- a/Makefile +++ b/Makefile @@ -2583,20 +2583,28 @@ LIBGRPC_SRC = \ src/core/ext/transport/chttp2/transport/writing.c \ src/core/ext/transport/chttp2/alpn/alpn.c \ src/core/lib/http/httpcli_security_connector.c \ - src/core/lib/security/b64.c \ - src/core/lib/security/client_auth_filter.c \ - src/core/lib/security/credentials.c \ - src/core/lib/security/credentials_metadata.c \ - src/core/lib/security/credentials_posix.c \ - src/core/lib/security/credentials_win32.c \ - src/core/lib/security/google_default_credentials.c \ - src/core/lib/security/handshake.c \ - src/core/lib/security/json_token.c \ - src/core/lib/security/jwt_verifier.c \ - src/core/lib/security/secure_endpoint.c \ - src/core/lib/security/security_connector.c \ - src/core/lib/security/security_context.c \ - src/core/lib/security/server_auth_filter.c \ + src/core/lib/security/context/security_context.c \ + src/core/lib/security/credentials/composite/composite_credentials.c \ + src/core/lib/security/credentials/credentials.c \ + src/core/lib/security/credentials/credentials_metadata.c \ + src/core/lib/security/credentials/fake/fake_credentials.c \ + src/core/lib/security/credentials/google_default/credentials_posix.c \ + src/core/lib/security/credentials/google_default/credentials_win32.c \ + src/core/lib/security/credentials/google_default/google_default_credentials.c \ + src/core/lib/security/credentials/iam/iam_credentials.c \ + src/core/lib/security/credentials/jwt/json_token.c \ + src/core/lib/security/credentials/jwt/jwt_credentials.c \ + src/core/lib/security/credentials/jwt/jwt_verifier.c \ + src/core/lib/security/credentials/oauth2/oauth2_credentials.c \ + src/core/lib/security/credentials/plugin/plugin_credentials.c \ + src/core/lib/security/credentials/ssl/ssl_credentials.c \ + src/core/lib/security/transport/client_auth_filter.c \ + src/core/lib/security/transport/handshake.c \ + src/core/lib/security/transport/secure_endpoint.c \ + src/core/lib/security/transport/security_connector.c \ + src/core/lib/security/transport/server_auth_filter.c \ + src/core/lib/security/util/b64.c \ + src/core/lib/security/util/json_util.c \ src/core/lib/surface/init_secure.c \ src/core/lib/tsi/fake_transport_security.c \ src/core/lib/tsi/ssl_transport_security.c \ @@ -14314,20 +14322,28 @@ ifneq ($(OPENSSL_DEP),) src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP) src/core/lib/http/httpcli_security_connector.c: $(OPENSSL_DEP) -src/core/lib/security/b64.c: $(OPENSSL_DEP) -src/core/lib/security/client_auth_filter.c: $(OPENSSL_DEP) -src/core/lib/security/credentials.c: $(OPENSSL_DEP) -src/core/lib/security/credentials_metadata.c: $(OPENSSL_DEP) -src/core/lib/security/credentials_posix.c: $(OPENSSL_DEP) -src/core/lib/security/credentials_win32.c: $(OPENSSL_DEP) -src/core/lib/security/google_default_credentials.c: $(OPENSSL_DEP) -src/core/lib/security/handshake.c: $(OPENSSL_DEP) -src/core/lib/security/json_token.c: $(OPENSSL_DEP) -src/core/lib/security/jwt_verifier.c: $(OPENSSL_DEP) -src/core/lib/security/secure_endpoint.c: $(OPENSSL_DEP) -src/core/lib/security/security_connector.c: $(OPENSSL_DEP) -src/core/lib/security/security_context.c: $(OPENSSL_DEP) -src/core/lib/security/server_auth_filter.c: $(OPENSSL_DEP) +src/core/lib/security/context/security_context.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/composite/composite_credentials.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/credentials.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/credentials_metadata.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/fake/fake_credentials.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/google_default/credentials_posix.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/google_default/credentials_win32.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/google_default/google_default_credentials.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/iam/iam_credentials.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/jwt/json_token.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/jwt/jwt_credentials.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/jwt/jwt_verifier.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/oauth2/oauth2_credentials.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/plugin/plugin_credentials.c: $(OPENSSL_DEP) +src/core/lib/security/credentials/ssl/ssl_credentials.c: $(OPENSSL_DEP) +src/core/lib/security/transport/client_auth_filter.c: $(OPENSSL_DEP) +src/core/lib/security/transport/handshake.c: $(OPENSSL_DEP) +src/core/lib/security/transport/secure_endpoint.c: $(OPENSSL_DEP) +src/core/lib/security/transport/security_connector.c: $(OPENSSL_DEP) +src/core/lib/security/transport/server_auth_filter.c: $(OPENSSL_DEP) +src/core/lib/security/util/b64.c: $(OPENSSL_DEP) +src/core/lib/security/util/json_util.c: $(OPENSSL_DEP) src/core/lib/surface/init_secure.c: $(OPENSSL_DEP) src/core/lib/tsi/fake_transport_security.c: $(OPENSSL_DEP) src/core/lib/tsi/ssl_transport_security.c: $(OPENSSL_DEP) diff --git a/binding.gyp b/binding.gyp index 4314ab7243..06e742ca43 100644 --- a/binding.gyp +++ b/binding.gyp @@ -669,20 +669,28 @@ 'src/core/ext/transport/chttp2/transport/writing.c', 'src/core/ext/transport/chttp2/alpn/alpn.c', 'src/core/lib/http/httpcli_security_connector.c', - 'src/core/lib/security/b64.c', - 'src/core/lib/security/client_auth_filter.c', - 'src/core/lib/security/credentials.c', - 'src/core/lib/security/credentials_metadata.c', - 'src/core/lib/security/credentials_posix.c', - 'src/core/lib/security/credentials_win32.c', - 'src/core/lib/security/google_default_credentials.c', - 'src/core/lib/security/handshake.c', - 'src/core/lib/security/json_token.c', - 'src/core/lib/security/jwt_verifier.c', - 'src/core/lib/security/secure_endpoint.c', - 'src/core/lib/security/security_connector.c', - 'src/core/lib/security/security_context.c', - 'src/core/lib/security/server_auth_filter.c', + 'src/core/lib/security/context/security_context.c', + 'src/core/lib/security/credentials/composite/composite_credentials.c', + 'src/core/lib/security/credentials/credentials.c', + 'src/core/lib/security/credentials/credentials_metadata.c', + 'src/core/lib/security/credentials/fake/fake_credentials.c', + 'src/core/lib/security/credentials/google_default/credentials_posix.c', + 'src/core/lib/security/credentials/google_default/credentials_win32.c', + 'src/core/lib/security/credentials/google_default/google_default_credentials.c', + 'src/core/lib/security/credentials/iam/iam_credentials.c', + 'src/core/lib/security/credentials/jwt/json_token.c', + 'src/core/lib/security/credentials/jwt/jwt_credentials.c', + 'src/core/lib/security/credentials/jwt/jwt_verifier.c', + 'src/core/lib/security/credentials/oauth2/oauth2_credentials.c', + 'src/core/lib/security/credentials/plugin/plugin_credentials.c', + 'src/core/lib/security/credentials/ssl/ssl_credentials.c', + 'src/core/lib/security/transport/client_auth_filter.c', + 'src/core/lib/security/transport/handshake.c', + 'src/core/lib/security/transport/secure_endpoint.c', + 'src/core/lib/security/transport/security_connector.c', + 'src/core/lib/security/transport/server_auth_filter.c', + 'src/core/lib/security/util/b64.c', + 'src/core/lib/security/util/json_util.c', 'src/core/lib/surface/init_secure.c', 'src/core/lib/tsi/fake_transport_security.c', 'src/core/lib/tsi/ssl_transport_security.c', diff --git a/build.yaml b/build.yaml index 441752dc3d..1d869009f4 100644 --- a/build.yaml +++ b/build.yaml @@ -402,31 +402,48 @@ filegroups: - include/grpc/grpc_security.h - include/grpc/grpc_security_constants.h headers: - - src/core/lib/security/auth_filters.h - - src/core/lib/security/b64.h - - src/core/lib/security/credentials.h - - src/core/lib/security/handshake.h - - src/core/lib/security/json_token.h - - src/core/lib/security/jwt_verifier.h - - src/core/lib/security/secure_endpoint.h - - src/core/lib/security/security_connector.h - - src/core/lib/security/security_context.h + - src/core/lib/security/context/security_context.h + - src/core/lib/security/credentials/composite/composite_credentials.h + - src/core/lib/security/credentials/credentials.h + - src/core/lib/security/credentials/fake/fake_credentials.h + - src/core/lib/security/credentials/google_default/google_default_credentials.h + - src/core/lib/security/credentials/iam/iam_credentials.h + - src/core/lib/security/credentials/jwt/json_token.h + - src/core/lib/security/credentials/jwt/jwt_credentials.h + - src/core/lib/security/credentials/jwt/jwt_verifier.h + - src/core/lib/security/credentials/oauth2/oauth2_credentials.h + - src/core/lib/security/credentials/plugin/plugin_credentials.h + - src/core/lib/security/credentials/ssl/ssl_credentials.h + - src/core/lib/security/transport/auth_filters.h + - src/core/lib/security/transport/handshake.h + - src/core/lib/security/transport/secure_endpoint.h + - src/core/lib/security/transport/security_connector.h + - src/core/lib/security/util/b64.h + - src/core/lib/security/util/json_util.h src: - src/core/lib/http/httpcli_security_connector.c - - src/core/lib/security/b64.c - - src/core/lib/security/client_auth_filter.c - - src/core/lib/security/credentials.c - - src/core/lib/security/credentials_metadata.c - - src/core/lib/security/credentials_posix.c - - src/core/lib/security/credentials_win32.c - - src/core/lib/security/google_default_credentials.c - - src/core/lib/security/handshake.c - - src/core/lib/security/json_token.c - - src/core/lib/security/jwt_verifier.c - - src/core/lib/security/secure_endpoint.c - - src/core/lib/security/security_connector.c - - src/core/lib/security/security_context.c - - src/core/lib/security/server_auth_filter.c + - src/core/lib/security/context/security_context.c + - src/core/lib/security/credentials/composite/composite_credentials.c + - src/core/lib/security/credentials/credentials.c + - src/core/lib/security/credentials/credentials_metadata.c + - src/core/lib/security/credentials/fake/fake_credentials.c + - src/core/lib/security/credentials/google_default/credentials_posix.c + - src/core/lib/security/credentials/google_default/credentials_win32.c + - src/core/lib/security/credentials/google_default/google_default_credentials.c + - src/core/lib/security/credentials/iam/iam_credentials.c + - src/core/lib/security/credentials/jwt/json_token.c + - src/core/lib/security/credentials/jwt/jwt_credentials.c + - src/core/lib/security/credentials/jwt/jwt_verifier.c + - src/core/lib/security/credentials/oauth2/oauth2_credentials.c + - src/core/lib/security/credentials/plugin/plugin_credentials.c + - src/core/lib/security/credentials/ssl/ssl_credentials.c + - src/core/lib/security/transport/client_auth_filter.c + - src/core/lib/security/transport/handshake.c + - src/core/lib/security/transport/secure_endpoint.c + - src/core/lib/security/transport/security_connector.c + - src/core/lib/security/transport/server_auth_filter.c + - src/core/lib/security/util/b64.c + - src/core/lib/security/util/json_util.c - src/core/lib/surface/init_secure.c secure: true uses: diff --git a/config.m4 b/config.m4 index 74f9ad242a..40e827d1dd 100644 --- a/config.m4 +++ b/config.m4 @@ -188,20 +188,28 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/transport/chttp2/transport/writing.c \ src/core/ext/transport/chttp2/alpn/alpn.c \ src/core/lib/http/httpcli_security_connector.c \ - src/core/lib/security/b64.c \ - src/core/lib/security/client_auth_filter.c \ - src/core/lib/security/credentials.c \ - src/core/lib/security/credentials_metadata.c \ - src/core/lib/security/credentials_posix.c \ - src/core/lib/security/credentials_win32.c \ - src/core/lib/security/google_default_credentials.c \ - src/core/lib/security/handshake.c \ - src/core/lib/security/json_token.c \ - src/core/lib/security/jwt_verifier.c \ - src/core/lib/security/secure_endpoint.c \ - src/core/lib/security/security_connector.c \ - src/core/lib/security/security_context.c \ - src/core/lib/security/server_auth_filter.c \ + src/core/lib/security/context/security_context.c \ + src/core/lib/security/credentials/composite/composite_credentials.c \ + src/core/lib/security/credentials/credentials.c \ + src/core/lib/security/credentials/credentials_metadata.c \ + src/core/lib/security/credentials/fake/fake_credentials.c \ + src/core/lib/security/credentials/google_default/credentials_posix.c \ + src/core/lib/security/credentials/google_default/credentials_win32.c \ + src/core/lib/security/credentials/google_default/google_default_credentials.c \ + src/core/lib/security/credentials/iam/iam_credentials.c \ + src/core/lib/security/credentials/jwt/json_token.c \ + src/core/lib/security/credentials/jwt/jwt_credentials.c \ + src/core/lib/security/credentials/jwt/jwt_verifier.c \ + src/core/lib/security/credentials/oauth2/oauth2_credentials.c \ + src/core/lib/security/credentials/plugin/plugin_credentials.c \ + src/core/lib/security/credentials/ssl/ssl_credentials.c \ + src/core/lib/security/transport/client_auth_filter.c \ + src/core/lib/security/transport/handshake.c \ + src/core/lib/security/transport/secure_endpoint.c \ + src/core/lib/security/transport/security_connector.c \ + src/core/lib/security/transport/server_auth_filter.c \ + src/core/lib/security/util/b64.c \ + src/core/lib/security/util/json_util.c \ src/core/lib/surface/init_secure.c \ src/core/lib/tsi/fake_transport_security.c \ src/core/lib/tsi/ssl_transport_security.c \ @@ -573,7 +581,18 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/iomgr) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/json) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/profiling) - PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/context) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/composite) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/fake) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/google_default) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/iam) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/jwt) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/oauth2) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/plugin) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/ssl) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/transport) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/util) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/support) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/surface) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/transport) diff --git a/gRPC.podspec b/gRPC.podspec index 77d35bd2c7..9ae4ea7c6e 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -257,15 +257,24 @@ Pod::Spec.new do |s| 'src/core/ext/transport/chttp2/transport/timeout_encoding.h', 'src/core/ext/transport/chttp2/transport/varint.h', 'src/core/ext/transport/chttp2/alpn/alpn.h', - 'src/core/lib/security/auth_filters.h', - 'src/core/lib/security/b64.h', - 'src/core/lib/security/credentials.h', - 'src/core/lib/security/handshake.h', - 'src/core/lib/security/json_token.h', - 'src/core/lib/security/jwt_verifier.h', - 'src/core/lib/security/secure_endpoint.h', - 'src/core/lib/security/security_connector.h', - 'src/core/lib/security/security_context.h', + 'src/core/lib/security/context/security_context.h', + 'src/core/lib/security/credentials/composite/composite_credentials.h', + 'src/core/lib/security/credentials/credentials.h', + 'src/core/lib/security/credentials/fake/fake_credentials.h', + 'src/core/lib/security/credentials/google_default/google_default_credentials.h', + 'src/core/lib/security/credentials/iam/iam_credentials.h', + 'src/core/lib/security/credentials/jwt/json_token.h', + 'src/core/lib/security/credentials/jwt/jwt_credentials.h', + 'src/core/lib/security/credentials/jwt/jwt_verifier.h', + 'src/core/lib/security/credentials/oauth2/oauth2_credentials.h', + 'src/core/lib/security/credentials/plugin/plugin_credentials.h', + 'src/core/lib/security/credentials/ssl/ssl_credentials.h', + 'src/core/lib/security/transport/auth_filters.h', + 'src/core/lib/security/transport/handshake.h', + 'src/core/lib/security/transport/secure_endpoint.h', + 'src/core/lib/security/transport/security_connector.h', + 'src/core/lib/security/util/b64.h', + 'src/core/lib/security/util/json_util.h', 'src/core/lib/tsi/fake_transport_security.h', 'src/core/lib/tsi/ssl_transport_security.h', 'src/core/lib/tsi/ssl_types.h', @@ -433,20 +442,28 @@ Pod::Spec.new do |s| 'src/core/ext/transport/chttp2/transport/writing.c', 'src/core/ext/transport/chttp2/alpn/alpn.c', 'src/core/lib/http/httpcli_security_connector.c', - 'src/core/lib/security/b64.c', - 'src/core/lib/security/client_auth_filter.c', - 'src/core/lib/security/credentials.c', - 'src/core/lib/security/credentials_metadata.c', - 'src/core/lib/security/credentials_posix.c', - 'src/core/lib/security/credentials_win32.c', - 'src/core/lib/security/google_default_credentials.c', - 'src/core/lib/security/handshake.c', - 'src/core/lib/security/json_token.c', - 'src/core/lib/security/jwt_verifier.c', - 'src/core/lib/security/secure_endpoint.c', - 'src/core/lib/security/security_connector.c', - 'src/core/lib/security/security_context.c', - 'src/core/lib/security/server_auth_filter.c', + 'src/core/lib/security/context/security_context.c', + 'src/core/lib/security/credentials/composite/composite_credentials.c', + 'src/core/lib/security/credentials/credentials.c', + 'src/core/lib/security/credentials/credentials_metadata.c', + 'src/core/lib/security/credentials/fake/fake_credentials.c', + 'src/core/lib/security/credentials/google_default/credentials_posix.c', + 'src/core/lib/security/credentials/google_default/credentials_win32.c', + 'src/core/lib/security/credentials/google_default/google_default_credentials.c', + 'src/core/lib/security/credentials/iam/iam_credentials.c', + 'src/core/lib/security/credentials/jwt/json_token.c', + 'src/core/lib/security/credentials/jwt/jwt_credentials.c', + 'src/core/lib/security/credentials/jwt/jwt_verifier.c', + 'src/core/lib/security/credentials/oauth2/oauth2_credentials.c', + 'src/core/lib/security/credentials/plugin/plugin_credentials.c', + 'src/core/lib/security/credentials/ssl/ssl_credentials.c', + 'src/core/lib/security/transport/client_auth_filter.c', + 'src/core/lib/security/transport/handshake.c', + 'src/core/lib/security/transport/secure_endpoint.c', + 'src/core/lib/security/transport/security_connector.c', + 'src/core/lib/security/transport/server_auth_filter.c', + 'src/core/lib/security/util/b64.c', + 'src/core/lib/security/util/json_util.c', 'src/core/lib/surface/init_secure.c', 'src/core/lib/tsi/fake_transport_security.c', 'src/core/lib/tsi/ssl_transport_security.c', @@ -599,15 +616,24 @@ Pod::Spec.new do |s| 'src/core/ext/transport/chttp2/transport/timeout_encoding.h', 'src/core/ext/transport/chttp2/transport/varint.h', 'src/core/ext/transport/chttp2/alpn/alpn.h', - 'src/core/lib/security/auth_filters.h', - 'src/core/lib/security/b64.h', - 'src/core/lib/security/credentials.h', - 'src/core/lib/security/handshake.h', - 'src/core/lib/security/json_token.h', - 'src/core/lib/security/jwt_verifier.h', - 'src/core/lib/security/secure_endpoint.h', - 'src/core/lib/security/security_connector.h', - 'src/core/lib/security/security_context.h', + 'src/core/lib/security/context/security_context.h', + 'src/core/lib/security/credentials/composite/composite_credentials.h', + 'src/core/lib/security/credentials/credentials.h', + 'src/core/lib/security/credentials/fake/fake_credentials.h', + 'src/core/lib/security/credentials/google_default/google_default_credentials.h', + 'src/core/lib/security/credentials/iam/iam_credentials.h', + 'src/core/lib/security/credentials/jwt/json_token.h', + 'src/core/lib/security/credentials/jwt/jwt_credentials.h', + 'src/core/lib/security/credentials/jwt/jwt_verifier.h', + 'src/core/lib/security/credentials/oauth2/oauth2_credentials.h', + 'src/core/lib/security/credentials/plugin/plugin_credentials.h', + 'src/core/lib/security/credentials/ssl/ssl_credentials.h', + 'src/core/lib/security/transport/auth_filters.h', + 'src/core/lib/security/transport/handshake.h', + 'src/core/lib/security/transport/secure_endpoint.h', + 'src/core/lib/security/transport/security_connector.h', + 'src/core/lib/security/util/b64.h', + 'src/core/lib/security/util/json_util.h', 'src/core/lib/tsi/fake_transport_security.h', 'src/core/lib/tsi/ssl_transport_security.h', 'src/core/lib/tsi/ssl_types.h', diff --git a/grpc.gemspec b/grpc.gemspec index e68cd81da7..ffdce9dd24 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -265,15 +265,24 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/transport/chttp2/transport/timeout_encoding.h ) s.files += %w( src/core/ext/transport/chttp2/transport/varint.h ) s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.h ) - s.files += %w( src/core/lib/security/auth_filters.h ) - s.files += %w( src/core/lib/security/b64.h ) - s.files += %w( src/core/lib/security/credentials.h ) - s.files += %w( src/core/lib/security/handshake.h ) - s.files += %w( src/core/lib/security/json_token.h ) - s.files += %w( src/core/lib/security/jwt_verifier.h ) - s.files += %w( src/core/lib/security/secure_endpoint.h ) - s.files += %w( src/core/lib/security/security_connector.h ) - s.files += %w( src/core/lib/security/security_context.h ) + s.files += %w( src/core/lib/security/context/security_context.h ) + s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.h ) + s.files += %w( src/core/lib/security/credentials/credentials.h ) + s.files += %w( src/core/lib/security/credentials/fake/fake_credentials.h ) + s.files += %w( src/core/lib/security/credentials/google_default/google_default_credentials.h ) + s.files += %w( src/core/lib/security/credentials/iam/iam_credentials.h ) + s.files += %w( src/core/lib/security/credentials/jwt/json_token.h ) + s.files += %w( src/core/lib/security/credentials/jwt/jwt_credentials.h ) + s.files += %w( src/core/lib/security/credentials/jwt/jwt_verifier.h ) + s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.h ) + s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h ) + s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h ) + s.files += %w( src/core/lib/security/transport/auth_filters.h ) + s.files += %w( src/core/lib/security/transport/handshake.h ) + s.files += %w( src/core/lib/security/transport/secure_endpoint.h ) + s.files += %w( src/core/lib/security/transport/security_connector.h ) + s.files += %w( src/core/lib/security/util/b64.h ) + s.files += %w( src/core/lib/security/util/json_util.h ) s.files += %w( src/core/lib/tsi/fake_transport_security.h ) s.files += %w( src/core/lib/tsi/ssl_transport_security.h ) s.files += %w( src/core/lib/tsi/ssl_types.h ) @@ -413,20 +422,28 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/transport/chttp2/transport/writing.c ) s.files += %w( src/core/ext/transport/chttp2/alpn/alpn.c ) s.files += %w( src/core/lib/http/httpcli_security_connector.c ) - s.files += %w( src/core/lib/security/b64.c ) - s.files += %w( src/core/lib/security/client_auth_filter.c ) - s.files += %w( src/core/lib/security/credentials.c ) - s.files += %w( src/core/lib/security/credentials_metadata.c ) - s.files += %w( src/core/lib/security/credentials_posix.c ) - s.files += %w( src/core/lib/security/credentials_win32.c ) - s.files += %w( src/core/lib/security/google_default_credentials.c ) - s.files += %w( src/core/lib/security/handshake.c ) - s.files += %w( src/core/lib/security/json_token.c ) - s.files += %w( src/core/lib/security/jwt_verifier.c ) - s.files += %w( src/core/lib/security/secure_endpoint.c ) - s.files += %w( src/core/lib/security/security_connector.c ) - s.files += %w( src/core/lib/security/security_context.c ) - s.files += %w( src/core/lib/security/server_auth_filter.c ) + s.files += %w( src/core/lib/security/context/security_context.c ) + s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.c ) + s.files += %w( src/core/lib/security/credentials/credentials.c ) + s.files += %w( src/core/lib/security/credentials/credentials_metadata.c ) + s.files += %w( src/core/lib/security/credentials/fake/fake_credentials.c ) + s.files += %w( src/core/lib/security/credentials/google_default/credentials_posix.c ) + s.files += %w( src/core/lib/security/credentials/google_default/credentials_win32.c ) + s.files += %w( src/core/lib/security/credentials/google_default/google_default_credentials.c ) + s.files += %w( src/core/lib/security/credentials/iam/iam_credentials.c ) + s.files += %w( src/core/lib/security/credentials/jwt/json_token.c ) + s.files += %w( src/core/lib/security/credentials/jwt/jwt_credentials.c ) + s.files += %w( src/core/lib/security/credentials/jwt/jwt_verifier.c ) + s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.c ) + s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.c ) + s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.c ) + s.files += %w( src/core/lib/security/transport/client_auth_filter.c ) + s.files += %w( src/core/lib/security/transport/handshake.c ) + s.files += %w( src/core/lib/security/transport/secure_endpoint.c ) + s.files += %w( src/core/lib/security/transport/security_connector.c ) + s.files += %w( src/core/lib/security/transport/server_auth_filter.c ) + s.files += %w( src/core/lib/security/util/b64.c ) + s.files += %w( src/core/lib/security/util/json_util.c ) s.files += %w( src/core/lib/surface/init_secure.c ) s.files += %w( src/core/lib/tsi/fake_transport_security.c ) s.files += %w( src/core/lib/tsi/ssl_transport_security.c ) diff --git a/package.xml b/package.xml index ffb1c56ed6..06c00bdb03 100644 --- a/package.xml +++ b/package.xml @@ -272,15 +272,24 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -420,20 +429,28 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index 58af6f995a..a262306085 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -45,9 +45,9 @@ #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/tcp_client.h" -#include "src/core/lib/security/auth_filters.h" -#include "src/core/lib/security/credentials.h" -#include "src/core/lib/security/security_context.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/transport/auth_filters.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/tsi/transport_security_interface.h" diff --git a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c index 698b2bef61..2c9f013c23 100644 --- a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c @@ -45,10 +45,10 @@ #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/tcp_server.h" -#include "src/core/lib/security/auth_filters.h" -#include "src/core/lib/security/credentials.h" -#include "src/core/lib/security/security_connector.h" -#include "src/core/lib/security/security_context.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/transport/auth_filters.h" +#include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/server.h" diff --git a/src/core/lib/http/httpcli_security_connector.c b/src/core/lib/http/httpcli_security_connector.c index ea4bff30d4..5590928968 100644 --- a/src/core/lib/http/httpcli_security_connector.c +++ b/src/core/lib/http/httpcli_security_connector.c @@ -38,7 +38,7 @@ #include #include #include -#include "src/core/lib/security/handshake.h" +#include "src/core/lib/security/transport/handshake.h" #include "src/core/lib/support/string.h" #include "src/core/lib/tsi/ssl_transport_security.h" diff --git a/src/core/lib/security/auth_filters.h b/src/core/lib/security/auth_filters.h deleted file mode 100644 index 7fb56c3f3a..0000000000 --- a/src/core/lib/security/auth_filters.h +++ /dev/null @@ -1,42 +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. - * - */ - -#ifndef GRPC_CORE_LIB_SECURITY_AUTH_FILTERS_H -#define GRPC_CORE_LIB_SECURITY_AUTH_FILTERS_H - -#include "src/core/lib/channel/channel_stack.h" - -extern const grpc_channel_filter grpc_client_auth_filter; -extern const grpc_channel_filter grpc_server_auth_filter; - -#endif /* GRPC_CORE_LIB_SECURITY_AUTH_FILTERS_H */ diff --git a/src/core/lib/security/b64.c b/src/core/lib/security/b64.c deleted file mode 100644 index 87f0e05280..0000000000 --- a/src/core/lib/security/b64.c +++ /dev/null @@ -1,233 +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 "src/core/lib/security/b64.h" - -#include -#include - -#include -#include -#include - -/* --- Constants. --- */ - -static const int8_t base64_bytes[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 0x3E, -1, -1, -1, 0x3F, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, -1, -1, - -1, 0x7F, -1, -1, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, - 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, -1, -1, -1, -1, -1, - -1, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, - 0x31, 0x32, 0x33, -1, -1, -1, -1, -1}; - -static const char base64_url_unsafe_chars[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char base64_url_safe_chars[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - -#define GRPC_BASE64_PAD_CHAR '=' -#define GRPC_BASE64_PAD_BYTE 0x7F -#define GRPC_BASE64_MULTILINE_LINE_LEN 76 -#define GRPC_BASE64_MULTILINE_NUM_BLOCKS (GRPC_BASE64_MULTILINE_LINE_LEN / 4) - -/* --- base64 functions. --- */ - -char *grpc_base64_encode(const void *vdata, size_t data_size, int url_safe, - int multiline) { - const unsigned char *data = vdata; - const char *base64_chars = - url_safe ? base64_url_safe_chars : base64_url_unsafe_chars; - size_t result_projected_size = - 4 * ((data_size + 3) / 3) + - 2 * (multiline ? (data_size / (3 * GRPC_BASE64_MULTILINE_NUM_BLOCKS)) - : 0) + - 1; - char *result = gpr_malloc(result_projected_size); - char *current = result; - size_t num_blocks = 0; - size_t i = 0; - - /* Encode each block. */ - while (data_size >= 3) { - *current++ = base64_chars[(data[i] >> 2) & 0x3F]; - *current++ = - base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)]; - *current++ = - base64_chars[((data[i + 1] & 0x0F) << 2) | ((data[i + 2] >> 6) & 0x03)]; - *current++ = base64_chars[data[i + 2] & 0x3F]; - - data_size -= 3; - i += 3; - if (multiline && (++num_blocks == GRPC_BASE64_MULTILINE_NUM_BLOCKS)) { - *current++ = '\r'; - *current++ = '\n'; - num_blocks = 0; - } - } - - /* Take care of the tail. */ - if (data_size == 2) { - *current++ = base64_chars[(data[i] >> 2) & 0x3F]; - *current++ = - base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)]; - *current++ = base64_chars[(data[i + 1] & 0x0F) << 2]; - *current++ = GRPC_BASE64_PAD_CHAR; - } else if (data_size == 1) { - *current++ = base64_chars[(data[i] >> 2) & 0x3F]; - *current++ = base64_chars[(data[i] & 0x03) << 4]; - *current++ = GRPC_BASE64_PAD_CHAR; - *current++ = GRPC_BASE64_PAD_CHAR; - } - - GPR_ASSERT(current >= result); - GPR_ASSERT((uintptr_t)(current - result) < result_projected_size); - result[current - result] = '\0'; - return result; -} - -gpr_slice grpc_base64_decode(const char *b64, int url_safe) { - return grpc_base64_decode_with_len(b64, strlen(b64), url_safe); -} - -static void decode_one_char(const unsigned char *codes, unsigned char *result, - size_t *result_offset) { - uint32_t packed = ((uint32_t)codes[0] << 2) | ((uint32_t)codes[1] >> 4); - result[(*result_offset)++] = (unsigned char)packed; -} - -static void decode_two_chars(const unsigned char *codes, unsigned char *result, - size_t *result_offset) { - uint32_t packed = ((uint32_t)codes[0] << 10) | ((uint32_t)codes[1] << 4) | - ((uint32_t)codes[2] >> 2); - result[(*result_offset)++] = (unsigned char)(packed >> 8); - result[(*result_offset)++] = (unsigned char)(packed); -} - -static int decode_group(const unsigned char *codes, size_t num_codes, - unsigned char *result, size_t *result_offset) { - GPR_ASSERT(num_codes <= 4); - - /* Short end groups that may not have padding. */ - if (num_codes == 1) { - gpr_log(GPR_ERROR, "Invalid group. Must be at least 2 bytes."); - return 0; - } - if (num_codes == 2) { - decode_one_char(codes, result, result_offset); - return 1; - } - if (num_codes == 3) { - decode_two_chars(codes, result, result_offset); - return 1; - } - - /* Regular 4 byte groups with padding or not. */ - GPR_ASSERT(num_codes == 4); - if (codes[0] == GRPC_BASE64_PAD_BYTE || codes[1] == GRPC_BASE64_PAD_BYTE) { - gpr_log(GPR_ERROR, "Invalid padding detected."); - return 0; - } - if (codes[2] == GRPC_BASE64_PAD_BYTE) { - if (codes[3] == GRPC_BASE64_PAD_BYTE) { - decode_one_char(codes, result, result_offset); - } else { - gpr_log(GPR_ERROR, "Invalid padding detected."); - return 0; - } - } else if (codes[3] == GRPC_BASE64_PAD_BYTE) { - decode_two_chars(codes, result, result_offset); - } else { - /* No padding. */ - uint32_t packed = ((uint32_t)codes[0] << 18) | ((uint32_t)codes[1] << 12) | - ((uint32_t)codes[2] << 6) | codes[3]; - result[(*result_offset)++] = (unsigned char)(packed >> 16); - result[(*result_offset)++] = (unsigned char)(packed >> 8); - result[(*result_offset)++] = (unsigned char)(packed); - } - return 1; -} - -gpr_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len, - int url_safe) { - gpr_slice result = gpr_slice_malloc(b64_len); - unsigned char *current = GPR_SLICE_START_PTR(result); - size_t result_size = 0; - unsigned char codes[4]; - size_t num_codes = 0; - - while (b64_len--) { - unsigned char c = (unsigned char)(*b64++); - signed char code; - if (c >= GPR_ARRAY_SIZE(base64_bytes)) continue; - if (url_safe) { - if (c == '+' || c == '/') { - gpr_log(GPR_ERROR, "Invalid character for url safe base64 %c", c); - goto fail; - } - if (c == '-') { - c = '+'; - } else if (c == '_') { - c = '/'; - } - } - code = base64_bytes[c]; - if (code == -1) { - if (c != '\r' && c != '\n') { - gpr_log(GPR_ERROR, "Invalid character %c", c); - goto fail; - } - } else { - codes[num_codes++] = (unsigned char)code; - if (num_codes == 4) { - if (!decode_group(codes, num_codes, current, &result_size)) goto fail; - num_codes = 0; - } - } - } - - if (num_codes != 0 && - !decode_group(codes, num_codes, current, &result_size)) { - goto fail; - } - GPR_SLICE_SET_LENGTH(result, result_size); - return result; - -fail: - gpr_slice_unref(result); - return gpr_empty_slice(); -} diff --git a/src/core/lib/security/b64.h b/src/core/lib/security/b64.h deleted file mode 100644 index c515e7af2c..0000000000 --- a/src/core/lib/security/b64.h +++ /dev/null @@ -1,52 +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. - * - */ - -#ifndef GRPC_CORE_LIB_SECURITY_B64_H -#define GRPC_CORE_LIB_SECURITY_B64_H - -#include - -/* Encodes data using base64. It is the caller's responsability to free - the returned char * using gpr_free. Returns NULL on NULL input. */ -char *grpc_base64_encode(const void *data, size_t data_size, int url_safe, - int multiline); - -/* Decodes data according to the base64 specification. Returns an empty - slice in case of failure. */ -gpr_slice grpc_base64_decode(const char *b64, int url_safe); - -/* Same as above except that the length is provided by the caller. */ -gpr_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len, - int url_safe); - -#endif /* GRPC_CORE_LIB_SECURITY_B64_H */ diff --git a/src/core/lib/security/client_auth_filter.c b/src/core/lib/security/client_auth_filter.c deleted file mode 100644 index 8b58cb86bf..0000000000 --- a/src/core/lib/security/client_auth_filter.c +++ /dev/null @@ -1,336 +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 "src/core/lib/security/auth_filters.h" - -#include - -#include -#include -#include - -#include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/security/credentials.h" -#include "src/core/lib/security/security_connector.h" -#include "src/core/lib/security/security_context.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/call.h" -#include "src/core/lib/transport/static_metadata.h" - -#define MAX_CREDENTIALS_METADATA_COUNT 4 - -/* We can have a per-call credentials. */ -typedef struct { - grpc_call_credentials *creds; - grpc_mdstr *host; - grpc_mdstr *method; - /* pollset bound to this call; if we need to make external - network requests, they should be done under this pollset - so that work can progress when this call wants work to - progress */ - grpc_pollset *pollset; - grpc_transport_stream_op op; - uint8_t security_context_set; - grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT]; - grpc_auth_metadata_context auth_md_context; -} call_data; - -/* We can have a per-channel credentials. */ -typedef struct { - grpc_channel_security_connector *security_connector; - grpc_auth_context *auth_context; -} channel_data; - -static void reset_auth_metadata_context( - grpc_auth_metadata_context *auth_md_context) { - if (auth_md_context->service_url != NULL) { - gpr_free((char *)auth_md_context->service_url); - auth_md_context->service_url = NULL; - } - if (auth_md_context->method_name != NULL) { - gpr_free((char *)auth_md_context->method_name); - auth_md_context->method_name = NULL; - } - GRPC_AUTH_CONTEXT_UNREF( - (grpc_auth_context *)auth_md_context->channel_auth_context, - "grpc_auth_metadata_context"); - auth_md_context->channel_auth_context = NULL; -} - -static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_status_code status, const char *error_msg) { - call_data *calld = elem->call_data; - gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg); - grpc_transport_stream_op_add_cancellation(&calld->op, status); - grpc_call_next_op(exec_ctx, elem, &calld->op); -} - -static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_credentials_md *md_elems, - size_t num_md, - grpc_credentials_status status) { - grpc_call_element *elem = (grpc_call_element *)user_data; - call_data *calld = elem->call_data; - grpc_transport_stream_op *op = &calld->op; - grpc_metadata_batch *mdb; - size_t i; - reset_auth_metadata_context(&calld->auth_md_context); - if (status != GRPC_CREDENTIALS_OK) { - bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, - "Credentials failed to get metadata."); - return; - } - GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT); - GPR_ASSERT(op->send_initial_metadata != NULL); - mdb = op->send_initial_metadata; - for (i = 0; i < num_md; i++) { - grpc_metadata_batch_add_tail( - mdb, &calld->md_links[i], - grpc_mdelem_from_slices(gpr_slice_ref(md_elems[i].key), - gpr_slice_ref(md_elems[i].value))); - } - grpc_call_next_op(exec_ctx, elem, op); -} - -void build_auth_metadata_context(grpc_security_connector *sc, - grpc_auth_context *auth_context, - call_data *calld) { - char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method)); - char *last_slash = strrchr(service, '/'); - char *method_name = NULL; - char *service_url = NULL; - reset_auth_metadata_context(&calld->auth_md_context); - if (last_slash == NULL) { - gpr_log(GPR_ERROR, "No '/' found in fully qualified method name"); - service[0] = '\0'; - } else if (last_slash == service) { - /* No service part in fully qualified method name: will just be "/". */ - service[1] = '\0'; - } else { - *last_slash = '\0'; - method_name = gpr_strdup(last_slash + 1); - } - if (method_name == NULL) method_name = gpr_strdup(""); - gpr_asprintf(&service_url, "%s://%s%s", - sc->url_scheme == NULL ? "" : sc->url_scheme, - grpc_mdstr_as_c_string(calld->host), service); - calld->auth_md_context.service_url = service_url; - calld->auth_md_context.method_name = method_name; - calld->auth_md_context.channel_auth_context = - GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context"); - gpr_free(service); -} - -static void send_security_metadata(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - grpc_transport_stream_op *op) { - call_data *calld = elem->call_data; - channel_data *chand = elem->channel_data; - grpc_client_security_context *ctx = - (grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value; - grpc_call_credentials *channel_call_creds = - chand->security_connector->request_metadata_creds; - int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL); - - if (channel_call_creds == NULL && !call_creds_has_md) { - /* Skip sending metadata altogether. */ - grpc_call_next_op(exec_ctx, elem, op); - return; - } - - if (channel_call_creds != NULL && call_creds_has_md) { - calld->creds = grpc_composite_call_credentials_create(channel_call_creds, - ctx->creds, NULL); - if (calld->creds == NULL) { - bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL, - "Incompatible credentials set on channel and call."); - return; - } - } else { - calld->creds = grpc_call_credentials_ref( - call_creds_has_md ? ctx->creds : channel_call_creds); - } - - build_auth_metadata_context(&chand->security_connector->base, - chand->auth_context, calld); - calld->op = *op; /* Copy op (originates from the caller's stack). */ - GPR_ASSERT(calld->pollset); - grpc_call_credentials_get_request_metadata( - exec_ctx, calld->creds, calld->pollset, calld->auth_md_context, - on_credentials_metadata, elem); -} - -static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_security_status status) { - grpc_call_element *elem = (grpc_call_element *)user_data; - call_data *calld = elem->call_data; - - if (status == GRPC_SECURITY_OK) { - send_security_metadata(exec_ctx, elem, &calld->op); - } else { - char *error_msg; - gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.", - grpc_mdstr_as_c_string(calld->host)); - bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL, error_msg); - gpr_free(error_msg); - } -} - -/* Called either: - - in response to an API call (or similar) from above, to send something - - a network event (or similar) from below, to receive something - op contains type and call direction information, in addition to the data - that is being sent or received. */ -static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - grpc_transport_stream_op *op) { - /* grab pointers to our data from the call element */ - call_data *calld = elem->call_data; - channel_data *chand = elem->channel_data; - grpc_linked_mdelem *l; - grpc_client_security_context *sec_ctx = NULL; - - if (calld->security_context_set == 0 && - op->cancel_with_status == GRPC_STATUS_OK) { - calld->security_context_set = 1; - GPR_ASSERT(op->context); - if (op->context[GRPC_CONTEXT_SECURITY].value == NULL) { - op->context[GRPC_CONTEXT_SECURITY].value = - grpc_client_security_context_create(); - op->context[GRPC_CONTEXT_SECURITY].destroy = - grpc_client_security_context_destroy; - } - sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value; - GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter"); - sec_ctx->auth_context = - GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter"); - } - - if (op->send_initial_metadata != NULL) { - for (l = op->send_initial_metadata->list.head; l != NULL; l = l->next) { - grpc_mdelem *md = l->md; - /* Pointer comparison is OK for md_elems created from the same context. - */ - if (md->key == GRPC_MDSTR_AUTHORITY) { - if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host); - calld->host = GRPC_MDSTR_REF(md->value); - } else if (md->key == GRPC_MDSTR_PATH) { - if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method); - calld->method = GRPC_MDSTR_REF(md->value); - } - } - if (calld->host != NULL) { - const char *call_host = grpc_mdstr_as_c_string(calld->host); - calld->op = *op; /* Copy op (originates from the caller's stack). */ - grpc_channel_security_connector_check_call_host( - exec_ctx, chand->security_connector, call_host, chand->auth_context, - on_host_checked, elem); - return; /* early exit */ - } - } - - /* pass control down the stack */ - grpc_call_next_op(exec_ctx, elem, op); -} - -/* Constructor for call_data */ -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { - call_data *calld = elem->call_data; - memset(calld, 0, sizeof(*calld)); -} - -static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_pollset *pollset) { - call_data *calld = elem->call_data; - calld->pollset = pollset; -} - -/* Destructor for call_data */ -static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - void *ignored) { - call_data *calld = elem->call_data; - grpc_call_credentials_unref(calld->creds); - if (calld->host != NULL) { - GRPC_MDSTR_UNREF(calld->host); - } - if (calld->method != NULL) { - GRPC_MDSTR_UNREF(calld->method); - } - reset_auth_metadata_context(&calld->auth_md_context); -} - -/* Constructor for channel_data */ -static void init_channel_elem(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem, - grpc_channel_element_args *args) { - grpc_security_connector *sc = - grpc_find_security_connector_in_args(args->channel_args); - grpc_auth_context *auth_context = - grpc_find_auth_context_in_args(args->channel_args); - - /* grab pointers to our data from the channel element */ - channel_data *chand = elem->channel_data; - - /* The first and the last filters tend to be implemented differently to - handle the case that there's no 'next' filter to call on the up or down - path */ - GPR_ASSERT(!args->is_last); - GPR_ASSERT(sc != NULL); - GPR_ASSERT(auth_context != NULL); - - /* initialize members */ - chand->security_connector = - (grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF( - sc, "client_auth_filter"); - chand->auth_context = - GRPC_AUTH_CONTEXT_REF(auth_context, "client_auth_filter"); -} - -/* Destructor for channel data */ -static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem) { - /* grab pointers to our data from the channel element */ - channel_data *chand = elem->channel_data; - grpc_channel_security_connector *sc = chand->security_connector; - if (sc != NULL) { - GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "client_auth_filter"); - } - GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter"); -} - -const grpc_channel_filter grpc_client_auth_filter = { - auth_start_transport_op, grpc_channel_next_op, sizeof(call_data), - init_call_elem, set_pollset, destroy_call_elem, - sizeof(channel_data), init_channel_elem, destroy_channel_elem, - grpc_call_next_get_peer, "client-auth"}; diff --git a/src/core/lib/security/context/security_context.c b/src/core/lib/security/context/security_context.c new file mode 100644 index 0000000000..127b13ee50 --- /dev/null +++ b/src/core/lib/security/context/security_context.c @@ -0,0 +1,347 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/api_trace.h" +#include "src/core/lib/surface/call.h" + +#include +#include +#include +#include + +/* --- grpc_call --- */ + +grpc_call_error grpc_call_set_credentials(grpc_call *call, + grpc_call_credentials *creds) { + grpc_client_security_context *ctx = NULL; + GRPC_API_TRACE("grpc_call_set_credentials(call=%p, creds=%p)", 2, + (call, creds)); + if (!grpc_call_is_client(call)) { + gpr_log(GPR_ERROR, "Method is client-side only."); + return GRPC_CALL_ERROR_NOT_ON_SERVER; + } + ctx = (grpc_client_security_context *)grpc_call_context_get( + call, GRPC_CONTEXT_SECURITY); + if (ctx == NULL) { + ctx = grpc_client_security_context_create(); + ctx->creds = grpc_call_credentials_ref(creds); + grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx, + grpc_client_security_context_destroy); + } else { + grpc_call_credentials_unref(ctx->creds); + ctx->creds = grpc_call_credentials_ref(creds); + } + return GRPC_CALL_OK; +} + +grpc_auth_context *grpc_call_auth_context(grpc_call *call) { + void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY); + GRPC_API_TRACE("grpc_call_auth_context(call=%p)", 1, (call)); + if (sec_ctx == NULL) return NULL; + return grpc_call_is_client(call) + ? GRPC_AUTH_CONTEXT_REF( + ((grpc_client_security_context *)sec_ctx)->auth_context, + "grpc_call_auth_context client") + : GRPC_AUTH_CONTEXT_REF( + ((grpc_server_security_context *)sec_ctx)->auth_context, + "grpc_call_auth_context server"); +} + +void grpc_auth_context_release(grpc_auth_context *context) { + GRPC_API_TRACE("grpc_auth_context_release(context=%p)", 1, (context)); + GRPC_AUTH_CONTEXT_UNREF(context, "grpc_auth_context_unref"); +} + +/* --- grpc_client_security_context --- */ + +grpc_client_security_context *grpc_client_security_context_create(void) { + grpc_client_security_context *ctx = + gpr_malloc(sizeof(grpc_client_security_context)); + memset(ctx, 0, sizeof(grpc_client_security_context)); + return ctx; +} + +void grpc_client_security_context_destroy(void *ctx) { + grpc_client_security_context *c = (grpc_client_security_context *)ctx; + grpc_call_credentials_unref(c->creds); + GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context"); + gpr_free(ctx); +} + +/* --- grpc_server_security_context --- */ + +grpc_server_security_context *grpc_server_security_context_create(void) { + grpc_server_security_context *ctx = + gpr_malloc(sizeof(grpc_server_security_context)); + memset(ctx, 0, sizeof(grpc_server_security_context)); + return ctx; +} + +void grpc_server_security_context_destroy(void *ctx) { + grpc_server_security_context *c = (grpc_server_security_context *)ctx; + GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "server_security_context"); + gpr_free(ctx); +} + +/* --- grpc_auth_context --- */ + +static grpc_auth_property_iterator empty_iterator = {NULL, 0, NULL}; + +grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained) { + grpc_auth_context *ctx = gpr_malloc(sizeof(grpc_auth_context)); + memset(ctx, 0, sizeof(grpc_auth_context)); + gpr_ref_init(&ctx->refcount, 1); + if (chained != NULL) { + ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained"); + ctx->peer_identity_property_name = + ctx->chained->peer_identity_property_name; + } + return ctx; +} + +#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG +grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx, + const char *file, int line, + const char *reason) { + if (ctx == NULL) return NULL; + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "AUTH_CONTEXT:%p ref %d -> %d %s", ctx, (int)ctx->refcount.count, + (int)ctx->refcount.count + 1, reason); +#else +grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx) { + if (ctx == NULL) return NULL; +#endif + gpr_ref(&ctx->refcount); + return ctx; +} + +#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG +void grpc_auth_context_unref(grpc_auth_context *ctx, const char *file, int line, + const char *reason) { + if (ctx == NULL) return; + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "AUTH_CONTEXT:%p unref %d -> %d %s", ctx, (int)ctx->refcount.count, + (int)ctx->refcount.count - 1, reason); +#else +void grpc_auth_context_unref(grpc_auth_context *ctx) { + if (ctx == NULL) return; +#endif + if (gpr_unref(&ctx->refcount)) { + size_t i; + GRPC_AUTH_CONTEXT_UNREF(ctx->chained, "chained"); + if (ctx->properties.array != NULL) { + for (i = 0; i < ctx->properties.count; i++) { + grpc_auth_property_reset(&ctx->properties.array[i]); + } + gpr_free(ctx->properties.array); + } + gpr_free(ctx); + } +} + +const char *grpc_auth_context_peer_identity_property_name( + const grpc_auth_context *ctx) { + GRPC_API_TRACE("grpc_auth_context_peer_identity_property_name(ctx=%p)", 1, + (ctx)); + return ctx->peer_identity_property_name; +} + +int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx, + const char *name) { + grpc_auth_property_iterator it = + grpc_auth_context_find_properties_by_name(ctx, name); + const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); + GRPC_API_TRACE( + "grpc_auth_context_set_peer_identity_property_name(ctx=%p, name=%s)", 2, + (ctx, name)); + if (prop == NULL) { + gpr_log(GPR_ERROR, "Property name %s not found in auth context.", + name != NULL ? name : "NULL"); + return 0; + } + ctx->peer_identity_property_name = prop->name; + return 1; +} + +int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx) { + GRPC_API_TRACE("grpc_auth_context_peer_is_authenticated(ctx=%p)", 1, (ctx)); + return ctx->peer_identity_property_name == NULL ? 0 : 1; +} + +grpc_auth_property_iterator grpc_auth_context_property_iterator( + const grpc_auth_context *ctx) { + grpc_auth_property_iterator it = empty_iterator; + GRPC_API_TRACE("grpc_auth_context_property_iterator(ctx=%p)", 1, (ctx)); + if (ctx == NULL) return it; + it.ctx = ctx; + return it; +} + +const grpc_auth_property *grpc_auth_property_iterator_next( + grpc_auth_property_iterator *it) { + GRPC_API_TRACE("grpc_auth_property_iterator_next(it=%p)", 1, (it)); + if (it == NULL || it->ctx == NULL) return NULL; + while (it->index == it->ctx->properties.count) { + if (it->ctx->chained == NULL) return NULL; + it->ctx = it->ctx->chained; + it->index = 0; + } + if (it->name == NULL) { + return &it->ctx->properties.array[it->index++]; + } else { + while (it->index < it->ctx->properties.count) { + const grpc_auth_property *prop = &it->ctx->properties.array[it->index++]; + GPR_ASSERT(prop->name != NULL); + if (strcmp(it->name, prop->name) == 0) { + return prop; + } + } + /* We could not find the name, try another round. */ + return grpc_auth_property_iterator_next(it); + } +} + +grpc_auth_property_iterator grpc_auth_context_find_properties_by_name( + const grpc_auth_context *ctx, const char *name) { + grpc_auth_property_iterator it = empty_iterator; + GRPC_API_TRACE("grpc_auth_context_find_properties_by_name(ctx=%p, name=%s)", + 2, (ctx, name)); + if (ctx == NULL || name == NULL) return empty_iterator; + it.ctx = ctx; + it.name = name; + return it; +} + +grpc_auth_property_iterator grpc_auth_context_peer_identity( + const grpc_auth_context *ctx) { + GRPC_API_TRACE("grpc_auth_context_peer_identity(ctx=%p)", 1, (ctx)); + if (ctx == NULL) return empty_iterator; + return grpc_auth_context_find_properties_by_name( + ctx, ctx->peer_identity_property_name); +} + +static void ensure_auth_context_capacity(grpc_auth_context *ctx) { + if (ctx->properties.count == ctx->properties.capacity) { + ctx->properties.capacity = + GPR_MAX(ctx->properties.capacity + 8, ctx->properties.capacity * 2); + ctx->properties.array = + gpr_realloc(ctx->properties.array, + ctx->properties.capacity * sizeof(grpc_auth_property)); + } +} + +void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name, + const char *value, size_t value_length) { + grpc_auth_property *prop; + GRPC_API_TRACE( + "grpc_auth_context_add_property(ctx=%p, name=%s, value=%*.*s, " + "value_length=%lu)", + 6, (ctx, name, (int)value_length, (int)value_length, value, + (unsigned long)value_length)); + ensure_auth_context_capacity(ctx); + prop = &ctx->properties.array[ctx->properties.count++]; + prop->name = gpr_strdup(name); + prop->value = gpr_malloc(value_length + 1); + memcpy(prop->value, value, value_length); + prop->value[value_length] = '\0'; + prop->value_length = value_length; +} + +void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx, + const char *name, + const char *value) { + grpc_auth_property *prop; + GRPC_API_TRACE( + "grpc_auth_context_add_cstring_property(ctx=%p, name=%s, value=%s)", 3, + (ctx, name, value)); + ensure_auth_context_capacity(ctx); + prop = &ctx->properties.array[ctx->properties.count++]; + prop->name = gpr_strdup(name); + prop->value = gpr_strdup(value); + prop->value_length = strlen(value); +} + +void grpc_auth_property_reset(grpc_auth_property *property) { + gpr_free(property->name); + gpr_free(property->value); + memset(property, 0, sizeof(grpc_auth_property)); +} + +static void auth_context_pointer_arg_destroy(void *p) { + GRPC_AUTH_CONTEXT_UNREF(p, "auth_context_pointer_arg"); +} + +static void *auth_context_pointer_arg_copy(void *p) { + return GRPC_AUTH_CONTEXT_REF(p, "auth_context_pointer_arg"); +} + +static int auth_context_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); } + +static const grpc_arg_pointer_vtable auth_context_pointer_vtable = { + auth_context_pointer_arg_copy, auth_context_pointer_arg_destroy, + auth_context_pointer_cmp}; + +grpc_arg grpc_auth_context_to_arg(grpc_auth_context *p) { + grpc_arg arg; + memset(&arg, 0, sizeof(grpc_arg)); + arg.type = GRPC_ARG_POINTER; + arg.key = GRPC_AUTH_CONTEXT_ARG; + arg.value.pointer.p = p; + arg.value.pointer.vtable = &auth_context_pointer_vtable; + return arg; +} + +grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg) { + if (strcmp(arg->key, GRPC_AUTH_CONTEXT_ARG) != 0) return NULL; + if (arg->type != GRPC_ARG_POINTER) { + gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, + GRPC_AUTH_CONTEXT_ARG); + return NULL; + } + return arg->value.pointer.p; +} + +grpc_auth_context *grpc_find_auth_context_in_args( + const grpc_channel_args *args) { + size_t i; + if (args == NULL) return NULL; + for (i = 0; i < args->num_args; i++) { + grpc_auth_context *p = grpc_auth_context_from_arg(&args->args[i]); + if (p != NULL) return p; + } + return NULL; +} diff --git a/src/core/lib/security/context/security_context.h b/src/core/lib/security/context/security_context.h new file mode 100644 index 0000000000..ef0c06b1fb --- /dev/null +++ b/src/core/lib/security/context/security_context.h @@ -0,0 +1,114 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H +#define GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H + +#include "src/core/lib/iomgr/pollset.h" +#include "src/core/lib/security/credentials/credentials.h" + +/* --- grpc_auth_context --- + + High level authentication context object. Can optionally be chained. */ + +/* Property names are always NULL terminated. */ + +typedef struct { + grpc_auth_property *array; + size_t count; + size_t capacity; +} grpc_auth_property_array; + +struct grpc_auth_context { + struct grpc_auth_context *chained; + grpc_auth_property_array properties; + gpr_refcount refcount; + const char *peer_identity_property_name; + grpc_pollset *pollset; +}; + +/* Creation. */ +grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained); + +/* Refcounting. */ +#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG +#define GRPC_AUTH_CONTEXT_REF(p, r) \ + grpc_auth_context_ref((p), __FILE__, __LINE__, (r)) +#define GRPC_AUTH_CONTEXT_UNREF(p, r) \ + grpc_auth_context_unref((p), __FILE__, __LINE__, (r)) +grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy, + const char *file, int line, + const char *reason); +void grpc_auth_context_unref(grpc_auth_context *policy, const char *file, + int line, const char *reason); +#else +#define GRPC_AUTH_CONTEXT_REF(p, r) grpc_auth_context_ref((p)) +#define GRPC_AUTH_CONTEXT_UNREF(p, r) grpc_auth_context_unref((p)) +grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy); +void grpc_auth_context_unref(grpc_auth_context *policy); +#endif + +void grpc_auth_property_reset(grpc_auth_property *property); + +/* --- grpc_client_security_context --- + + Internal client-side security context. */ + +typedef struct { + grpc_call_credentials *creds; + grpc_auth_context *auth_context; +} grpc_client_security_context; + +grpc_client_security_context *grpc_client_security_context_create(void); +void grpc_client_security_context_destroy(void *ctx); + +/* --- grpc_server_security_context --- + + Internal server-side security context. */ + +typedef struct { + grpc_auth_context *auth_context; +} grpc_server_security_context; + +grpc_server_security_context *grpc_server_security_context_create(void); +void grpc_server_security_context_destroy(void *ctx); + +/* --- Channel args for auth context --- */ +#define GRPC_AUTH_CONTEXT_ARG "grpc.auth_context" + +grpc_arg grpc_auth_context_to_arg(grpc_auth_context *c); +grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg); +grpc_auth_context *grpc_find_auth_context_in_args( + const grpc_channel_args *args); + +#endif /* GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H */ diff --git a/src/core/lib/security/credentials.c b/src/core/lib/security/credentials.c deleted file mode 100644 index fd5ad3589b..0000000000 --- a/src/core/lib/security/credentials.c +++ /dev/null @@ -1,1296 +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 "src/core/lib/security/credentials.h" - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/http_client_filter.h" -#include "src/core/lib/http/httpcli.h" -#include "src/core/lib/http/parser.h" -#include "src/core/lib/iomgr/executor.h" -#include "src/core/lib/json/json.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/api_trace.h" - -#include -#include -#include -#include -#include - -/* -- Common. -- */ - -struct grpc_credentials_metadata_request { - grpc_call_credentials *creds; - grpc_credentials_metadata_cb cb; - void *user_data; -}; - -static grpc_credentials_metadata_request * -grpc_credentials_metadata_request_create(grpc_call_credentials *creds, - grpc_credentials_metadata_cb cb, - void *user_data) { - grpc_credentials_metadata_request *r = - gpr_malloc(sizeof(grpc_credentials_metadata_request)); - r->creds = grpc_call_credentials_ref(creds); - r->cb = cb; - r->user_data = user_data; - return r; -} - -static void grpc_credentials_metadata_request_destroy( - grpc_credentials_metadata_request *r) { - grpc_call_credentials_unref(r->creds); - gpr_free(r); -} - -grpc_channel_credentials *grpc_channel_credentials_ref( - grpc_channel_credentials *creds) { - if (creds == NULL) return NULL; - gpr_ref(&creds->refcount); - return creds; -} - -void grpc_channel_credentials_unref(grpc_channel_credentials *creds) { - if (creds == NULL) return; - if (gpr_unref(&creds->refcount)) { - if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds); - gpr_free(creds); - } -} - -void grpc_channel_credentials_release(grpc_channel_credentials *creds) { - GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds)); - grpc_channel_credentials_unref(creds); -} - -grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) { - if (creds == NULL) return NULL; - gpr_ref(&creds->refcount); - return creds; -} - -void grpc_call_credentials_unref(grpc_call_credentials *creds) { - if (creds == NULL) return; - if (gpr_unref(&creds->refcount)) { - if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds); - gpr_free(creds); - } -} - -void grpc_call_credentials_release(grpc_call_credentials *creds) { - GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds)); - grpc_call_credentials_unref(creds); -} - -void grpc_call_credentials_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, - grpc_pollset *pollset, grpc_auth_metadata_context context, - grpc_credentials_metadata_cb cb, void *user_data) { - if (creds == NULL || creds->vtable->get_request_metadata == NULL) { - if (cb != NULL) { - cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK); - } - return; - } - creds->vtable->get_request_metadata(exec_ctx, creds, pollset, context, cb, - user_data); -} - -grpc_security_status grpc_channel_credentials_create_security_connector( - grpc_channel_credentials *channel_creds, const char *target, - const grpc_channel_args *args, grpc_channel_security_connector **sc, - grpc_channel_args **new_args) { - *new_args = NULL; - if (channel_creds == NULL) { - return GRPC_SECURITY_ERROR; - } - GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL); - return channel_creds->vtable->create_security_connector( - channel_creds, NULL, target, args, sc, new_args); -} - -grpc_server_credentials *grpc_server_credentials_ref( - grpc_server_credentials *creds) { - if (creds == NULL) return NULL; - gpr_ref(&creds->refcount); - return creds; -} - -void grpc_server_credentials_unref(grpc_server_credentials *creds) { - if (creds == NULL) return; - if (gpr_unref(&creds->refcount)) { - if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds); - if (creds->processor.destroy != NULL && creds->processor.state != NULL) { - creds->processor.destroy(creds->processor.state); - } - gpr_free(creds); - } -} - -void grpc_server_credentials_release(grpc_server_credentials *creds) { - GRPC_API_TRACE("grpc_server_credentials_release(creds=%p)", 1, (creds)); - grpc_server_credentials_unref(creds); -} - -grpc_security_status grpc_server_credentials_create_security_connector( - grpc_server_credentials *creds, grpc_server_security_connector **sc) { - if (creds == NULL || creds->vtable->create_security_connector == NULL) { - gpr_log(GPR_ERROR, "Server credentials cannot create security context."); - return GRPC_SECURITY_ERROR; - } - return creds->vtable->create_security_connector(creds, sc); -} - -void grpc_server_credentials_set_auth_metadata_processor( - grpc_server_credentials *creds, grpc_auth_metadata_processor processor) { - GRPC_API_TRACE( - "grpc_server_credentials_set_auth_metadata_processor(" - "creds=%p, " - "processor=grpc_auth_metadata_processor { process: %p, state: %p })", - 3, (creds, (void *)(intptr_t)processor.process, processor.state)); - if (creds == NULL) return; - if (creds->processor.destroy != NULL && creds->processor.state != NULL) { - creds->processor.destroy(creds->processor.state); - } - creds->processor = processor; -} - -static void server_credentials_pointer_arg_destroy(void *p) { - grpc_server_credentials_unref(p); -} - -static void *server_credentials_pointer_arg_copy(void *p) { - return grpc_server_credentials_ref(p); -} - -static int server_credentials_pointer_cmp(void *a, void *b) { - return GPR_ICMP(a, b); -} - -static const grpc_arg_pointer_vtable cred_ptr_vtable = { - server_credentials_pointer_arg_copy, server_credentials_pointer_arg_destroy, - server_credentials_pointer_cmp}; - -grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) { - grpc_arg arg; - memset(&arg, 0, sizeof(grpc_arg)); - arg.type = GRPC_ARG_POINTER; - arg.key = GRPC_SERVER_CREDENTIALS_ARG; - arg.value.pointer.p = p; - arg.value.pointer.vtable = &cred_ptr_vtable; - return arg; -} - -grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg) { - if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL; - if (arg->type != GRPC_ARG_POINTER) { - gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, - GRPC_SERVER_CREDENTIALS_ARG); - return NULL; - } - return arg->value.pointer.p; -} - -grpc_server_credentials *grpc_find_server_credentials_in_args( - const grpc_channel_args *args) { - size_t i; - if (args == NULL) return NULL; - for (i = 0; i < args->num_args; i++) { - grpc_server_credentials *p = - grpc_server_credentials_from_arg(&args->args[i]); - if (p != NULL) return p; - } - return NULL; -} - -/* -- Ssl credentials. -- */ - -static void ssl_destruct(grpc_channel_credentials *creds) { - grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; - if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); - if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key); - if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain); -} - -static void ssl_server_destruct(grpc_server_credentials *creds) { - grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds; - size_t i; - for (i = 0; i < c->config.num_key_cert_pairs; i++) { - if (c->config.pem_private_keys[i] != NULL) { - gpr_free(c->config.pem_private_keys[i]); - } - if (c->config.pem_cert_chains[i] != NULL) { - gpr_free(c->config.pem_cert_chains[i]); - } - } - if (c->config.pem_private_keys != NULL) gpr_free(c->config.pem_private_keys); - if (c->config.pem_private_keys_sizes != NULL) { - gpr_free(c->config.pem_private_keys_sizes); - } - if (c->config.pem_cert_chains != NULL) gpr_free(c->config.pem_cert_chains); - if (c->config.pem_cert_chains_sizes != NULL) { - gpr_free(c->config.pem_cert_chains_sizes); - } - if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); -} - -static grpc_security_status ssl_create_security_connector( - grpc_channel_credentials *creds, grpc_call_credentials *call_creds, - const char *target, const grpc_channel_args *args, - grpc_channel_security_connector **sc, grpc_channel_args **new_args) { - grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; - grpc_security_status status = GRPC_SECURITY_OK; - size_t i = 0; - const char *overridden_target_name = NULL; - grpc_arg new_arg; - - for (i = 0; args && i < args->num_args; i++) { - grpc_arg *arg = &args->args[i]; - if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 && - arg->type == GRPC_ARG_STRING) { - overridden_target_name = arg->value.string; - break; - } - } - status = grpc_ssl_channel_security_connector_create( - call_creds, &c->config, target, overridden_target_name, sc); - if (status != GRPC_SECURITY_OK) { - return status; - } - new_arg.type = GRPC_ARG_STRING; - new_arg.key = GRPC_ARG_HTTP2_SCHEME; - new_arg.value.string = "https"; - *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1); - return status; -} - -static grpc_security_status ssl_server_create_security_connector( - grpc_server_credentials *creds, grpc_server_security_connector **sc) { - grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds; - return grpc_ssl_server_security_connector_create(&c->config, sc); -} - -static grpc_channel_credentials_vtable ssl_vtable = { - ssl_destruct, ssl_create_security_connector}; - -static grpc_server_credentials_vtable ssl_server_vtable = { - ssl_server_destruct, ssl_server_create_security_connector}; - -static void ssl_copy_key_material(const char *input, unsigned char **output, - size_t *output_size) { - *output_size = strlen(input); - *output = gpr_malloc(*output_size); - memcpy(*output, input, *output_size); -} - -static void ssl_build_config(const char *pem_root_certs, - grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, - grpc_ssl_config *config) { - if (pem_root_certs != NULL) { - ssl_copy_key_material(pem_root_certs, &config->pem_root_certs, - &config->pem_root_certs_size); - } - if (pem_key_cert_pair != NULL) { - GPR_ASSERT(pem_key_cert_pair->private_key != NULL); - GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL); - ssl_copy_key_material(pem_key_cert_pair->private_key, - &config->pem_private_key, - &config->pem_private_key_size); - ssl_copy_key_material(pem_key_cert_pair->cert_chain, - &config->pem_cert_chain, - &config->pem_cert_chain_size); - } -} - -static void ssl_build_server_config( - const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, - size_t num_key_cert_pairs, - grpc_ssl_client_certificate_request_type client_certificate_request, - grpc_ssl_server_config *config) { - size_t i; - config->client_certificate_request = client_certificate_request; - if (pem_root_certs != NULL) { - ssl_copy_key_material(pem_root_certs, &config->pem_root_certs, - &config->pem_root_certs_size); - } - if (num_key_cert_pairs > 0) { - GPR_ASSERT(pem_key_cert_pairs != NULL); - config->pem_private_keys = - gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *)); - config->pem_cert_chains = - gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *)); - config->pem_private_keys_sizes = - gpr_malloc(num_key_cert_pairs * sizeof(size_t)); - config->pem_cert_chains_sizes = - gpr_malloc(num_key_cert_pairs * sizeof(size_t)); - } - config->num_key_cert_pairs = num_key_cert_pairs; - for (i = 0; i < num_key_cert_pairs; i++) { - GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL); - GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL); - ssl_copy_key_material(pem_key_cert_pairs[i].private_key, - &config->pem_private_keys[i], - &config->pem_private_keys_sizes[i]); - ssl_copy_key_material(pem_key_cert_pairs[i].cert_chain, - &config->pem_cert_chains[i], - &config->pem_cert_chains_sizes[i]); - } -} - -grpc_channel_credentials *grpc_ssl_credentials_create( - const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, - void *reserved) { - grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials)); - GRPC_API_TRACE( - "grpc_ssl_credentials_create(pem_root_certs=%s, " - "pem_key_cert_pair=%p, " - "reserved=%p)", - 3, (pem_root_certs, pem_key_cert_pair, reserved)); - GPR_ASSERT(reserved == NULL); - memset(c, 0, sizeof(grpc_ssl_credentials)); - c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; - c->base.vtable = &ssl_vtable; - gpr_ref_init(&c->base.refcount, 1); - ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config); - return &c->base; -} - -grpc_server_credentials *grpc_ssl_server_credentials_create( - const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, - size_t num_key_cert_pairs, int force_client_auth, void *reserved) { - return grpc_ssl_server_credentials_create_ex( - pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs, - force_client_auth - ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY - : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, - reserved); -} - -grpc_server_credentials *grpc_ssl_server_credentials_create_ex( - const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, - size_t num_key_cert_pairs, - grpc_ssl_client_certificate_request_type client_certificate_request, - void *reserved) { - grpc_ssl_server_credentials *c = - gpr_malloc(sizeof(grpc_ssl_server_credentials)); - GRPC_API_TRACE( - "grpc_ssl_server_credentials_create_ex(" - "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, " - "client_certificate_request=%d, reserved=%p)", - 5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs, - client_certificate_request, reserved)); - GPR_ASSERT(reserved == NULL); - memset(c, 0, sizeof(grpc_ssl_server_credentials)); - c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; - gpr_ref_init(&c->base.refcount, 1); - c->base.vtable = &ssl_server_vtable; - ssl_build_server_config(pem_root_certs, pem_key_cert_pairs, - num_key_cert_pairs, client_certificate_request, - &c->config); - return &c->base; -} - -/* -- Jwt credentials -- */ - -static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) { - if (c->cached.jwt_md != NULL) { - grpc_credentials_md_store_unref(c->cached.jwt_md); - c->cached.jwt_md = NULL; - } - if (c->cached.service_url != NULL) { - gpr_free(c->cached.service_url); - c->cached.service_url = NULL; - } - c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); -} - -static void jwt_destruct(grpc_call_credentials *creds) { - grpc_service_account_jwt_access_credentials *c = - (grpc_service_account_jwt_access_credentials *)creds; - grpc_auth_json_key_destruct(&c->key); - jwt_reset_cache(c); - gpr_mu_destroy(&c->cache_mu); -} - -static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx, - grpc_call_credentials *creds, - grpc_pollset *pollset, - grpc_auth_metadata_context context, - grpc_credentials_metadata_cb cb, - void *user_data) { - grpc_service_account_jwt_access_credentials *c = - (grpc_service_account_jwt_access_credentials *)creds; - gpr_timespec refresh_threshold = gpr_time_from_seconds( - GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN); - - /* See if we can return a cached jwt. */ - grpc_credentials_md_store *jwt_md = NULL; - { - gpr_mu_lock(&c->cache_mu); - if (c->cached.service_url != NULL && - strcmp(c->cached.service_url, context.service_url) == 0 && - c->cached.jwt_md != NULL && - (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, - gpr_now(GPR_CLOCK_REALTIME)), - refresh_threshold) > 0)) { - jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md); - } - gpr_mu_unlock(&c->cache_mu); - } - - if (jwt_md == NULL) { - char *jwt = NULL; - /* Generate a new jwt. */ - gpr_mu_lock(&c->cache_mu); - jwt_reset_cache(c); - jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url, - c->jwt_lifetime, NULL); - if (jwt != NULL) { - char *md_value; - gpr_asprintf(&md_value, "Bearer %s", jwt); - gpr_free(jwt); - c->cached.jwt_expiration = - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime); - c->cached.service_url = gpr_strdup(context.service_url); - c->cached.jwt_md = grpc_credentials_md_store_create(1); - grpc_credentials_md_store_add_cstrings( - c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value); - gpr_free(md_value); - jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md); - } - gpr_mu_unlock(&c->cache_mu); - } - - if (jwt_md != NULL) { - cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries, - GRPC_CREDENTIALS_OK); - grpc_credentials_md_store_unref(jwt_md); - } else { - cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); - } -} - -static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct, - jwt_get_request_metadata}; - -grpc_call_credentials * -grpc_service_account_jwt_access_credentials_create_from_auth_json_key( - grpc_auth_json_key key, gpr_timespec token_lifetime) { - grpc_service_account_jwt_access_credentials *c; - if (!grpc_auth_json_key_is_valid(&key)) { - gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation"); - return NULL; - } - c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials)); - memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials)); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT; - gpr_ref_init(&c->base.refcount, 1); - c->base.vtable = &jwt_vtable; - c->key = key; - c->jwt_lifetime = token_lifetime; - gpr_mu_init(&c->cache_mu); - jwt_reset_cache(c); - return &c->base; -} - -grpc_call_credentials *grpc_service_account_jwt_access_credentials_create( - const char *json_key, gpr_timespec token_lifetime, void *reserved) { - GRPC_API_TRACE( - "grpc_service_account_jwt_access_credentials_create(" - "json_key=%s, " - "token_lifetime=" - "gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, " - "reserved=%p)", - 5, - (json_key, (long long)token_lifetime.tv_sec, (int)token_lifetime.tv_nsec, - (int)token_lifetime.clock_type, reserved)); - GPR_ASSERT(reserved == NULL); - return grpc_service_account_jwt_access_credentials_create_from_auth_json_key( - grpc_auth_json_key_create_from_string(json_key), token_lifetime); -} - -/* -- Oauth2TokenFetcher credentials -- */ - -static void oauth2_token_fetcher_destruct(grpc_call_credentials *creds) { - grpc_oauth2_token_fetcher_credentials *c = - (grpc_oauth2_token_fetcher_credentials *)creds; - grpc_credentials_md_store_unref(c->access_token_md); - gpr_mu_destroy(&c->mu); - grpc_httpcli_context_destroy(&c->httpcli_context); -} - -grpc_credentials_status -grpc_oauth2_token_fetcher_credentials_parse_server_response( - const grpc_http_response *response, grpc_credentials_md_store **token_md, - gpr_timespec *token_lifetime) { - char *null_terminated_body = NULL; - char *new_access_token = NULL; - grpc_credentials_status status = GRPC_CREDENTIALS_OK; - grpc_json *json = NULL; - - if (response == NULL) { - gpr_log(GPR_ERROR, "Received NULL response."); - status = GRPC_CREDENTIALS_ERROR; - goto end; - } - - if (response->body_length > 0) { - null_terminated_body = gpr_malloc(response->body_length + 1); - null_terminated_body[response->body_length] = '\0'; - memcpy(null_terminated_body, response->body, response->body_length); - } - - if (response->status != 200) { - gpr_log(GPR_ERROR, "Call to http server ended with error %d [%s].", - response->status, - null_terminated_body != NULL ? null_terminated_body : ""); - status = GRPC_CREDENTIALS_ERROR; - goto end; - } else { - grpc_json *access_token = NULL; - grpc_json *token_type = NULL; - grpc_json *expires_in = NULL; - grpc_json *ptr; - json = grpc_json_parse_string(null_terminated_body); - if (json == NULL) { - gpr_log(GPR_ERROR, "Could not parse JSON from %s", null_terminated_body); - status = GRPC_CREDENTIALS_ERROR; - goto end; - } - if (json->type != GRPC_JSON_OBJECT) { - gpr_log(GPR_ERROR, "Response should be a JSON object"); - status = GRPC_CREDENTIALS_ERROR; - goto end; - } - for (ptr = json->child; ptr; ptr = ptr->next) { - if (strcmp(ptr->key, "access_token") == 0) { - access_token = ptr; - } else if (strcmp(ptr->key, "token_type") == 0) { - token_type = ptr; - } else if (strcmp(ptr->key, "expires_in") == 0) { - expires_in = ptr; - } - } - if (access_token == NULL || access_token->type != GRPC_JSON_STRING) { - gpr_log(GPR_ERROR, "Missing or invalid access_token in JSON."); - status = GRPC_CREDENTIALS_ERROR; - goto end; - } - if (token_type == NULL || token_type->type != GRPC_JSON_STRING) { - gpr_log(GPR_ERROR, "Missing or invalid token_type in JSON."); - status = GRPC_CREDENTIALS_ERROR; - goto end; - } - if (expires_in == NULL || expires_in->type != GRPC_JSON_NUMBER) { - gpr_log(GPR_ERROR, "Missing or invalid expires_in in JSON."); - status = GRPC_CREDENTIALS_ERROR; - goto end; - } - gpr_asprintf(&new_access_token, "%s %s", token_type->value, - access_token->value); - token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10); - token_lifetime->tv_nsec = 0; - token_lifetime->clock_type = GPR_TIMESPAN; - if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md); - *token_md = grpc_credentials_md_store_create(1); - grpc_credentials_md_store_add_cstrings( - *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token); - status = GRPC_CREDENTIALS_OK; - } - -end: - if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) { - grpc_credentials_md_store_unref(*token_md); - *token_md = NULL; - } - if (null_terminated_body != NULL) gpr_free(null_terminated_body); - if (new_access_token != NULL) gpr_free(new_access_token); - if (json != NULL) grpc_json_destroy(json); - return status; -} - -static void on_oauth2_token_fetcher_http_response( - grpc_exec_ctx *exec_ctx, void *user_data, - const grpc_http_response *response) { - grpc_credentials_metadata_request *r = - (grpc_credentials_metadata_request *)user_data; - grpc_oauth2_token_fetcher_credentials *c = - (grpc_oauth2_token_fetcher_credentials *)r->creds; - gpr_timespec token_lifetime; - grpc_credentials_status status; - - gpr_mu_lock(&c->mu); - status = grpc_oauth2_token_fetcher_credentials_parse_server_response( - response, &c->access_token_md, &token_lifetime); - if (status == GRPC_CREDENTIALS_OK) { - c->token_expiration = - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime); - r->cb(exec_ctx, r->user_data, c->access_token_md->entries, - c->access_token_md->num_entries, status); - } else { - c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); - r->cb(exec_ctx, r->user_data, NULL, 0, status); - } - gpr_mu_unlock(&c->mu); - grpc_credentials_metadata_request_destroy(r); -} - -static void oauth2_token_fetcher_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, - grpc_pollset *pollset, grpc_auth_metadata_context context, - grpc_credentials_metadata_cb cb, void *user_data) { - grpc_oauth2_token_fetcher_credentials *c = - (grpc_oauth2_token_fetcher_credentials *)creds; - gpr_timespec refresh_threshold = gpr_time_from_seconds( - GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN); - grpc_credentials_md_store *cached_access_token_md = NULL; - { - gpr_mu_lock(&c->mu); - if (c->access_token_md != NULL && - (gpr_time_cmp( - gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)), - refresh_threshold) > 0)) { - cached_access_token_md = - grpc_credentials_md_store_ref(c->access_token_md); - } - gpr_mu_unlock(&c->mu); - } - if (cached_access_token_md != NULL) { - cb(exec_ctx, user_data, cached_access_token_md->entries, - cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK); - grpc_credentials_md_store_unref(cached_access_token_md); - } else { - c->fetch_func( - exec_ctx, - grpc_credentials_metadata_request_create(creds, cb, user_data), - &c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response, - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold)); - } -} - -static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c, - grpc_fetch_oauth2_func fetch_func) { - memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials)); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; - gpr_ref_init(&c->base.refcount, 1); - gpr_mu_init(&c->mu); - c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); - c->fetch_func = fetch_func; - grpc_httpcli_context_init(&c->httpcli_context); -} - -/* -- GoogleComputeEngine credentials. -- */ - -static grpc_call_credentials_vtable compute_engine_vtable = { - oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata}; - -static void compute_engine_fetch_oauth2( - grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req, - grpc_httpcli_context *httpcli_context, grpc_pollset *pollset, - grpc_httpcli_response_cb response_cb, gpr_timespec deadline) { - grpc_http_header header = {"Metadata-Flavor", "Google"}; - grpc_httpcli_request request; - memset(&request, 0, sizeof(grpc_httpcli_request)); - request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST; - request.http.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH; - request.http.hdr_count = 1; - request.http.hdrs = &header; - grpc_httpcli_get(exec_ctx, httpcli_context, pollset, &request, deadline, - response_cb, metadata_req); -} - -grpc_call_credentials *grpc_google_compute_engine_credentials_create( - void *reserved) { - grpc_oauth2_token_fetcher_credentials *c = - gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials)); - GRPC_API_TRACE("grpc_compute_engine_credentials_create(reserved=%p)", 1, - (reserved)); - GPR_ASSERT(reserved == NULL); - init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2); - c->base.vtable = &compute_engine_vtable; - return &c->base; -} - -/* -- GoogleRefreshToken credentials. -- */ - -static void refresh_token_destruct(grpc_call_credentials *creds) { - grpc_google_refresh_token_credentials *c = - (grpc_google_refresh_token_credentials *)creds; - grpc_auth_refresh_token_destruct(&c->refresh_token); - oauth2_token_fetcher_destruct(&c->base.base); -} - -static grpc_call_credentials_vtable refresh_token_vtable = { - refresh_token_destruct, oauth2_token_fetcher_get_request_metadata}; - -static void refresh_token_fetch_oauth2( - grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req, - grpc_httpcli_context *httpcli_context, grpc_pollset *pollset, - grpc_httpcli_response_cb response_cb, gpr_timespec deadline) { - grpc_google_refresh_token_credentials *c = - (grpc_google_refresh_token_credentials *)metadata_req->creds; - grpc_http_header header = {"Content-Type", - "application/x-www-form-urlencoded"}; - grpc_httpcli_request request; - char *body = NULL; - gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING, - c->refresh_token.client_id, c->refresh_token.client_secret, - c->refresh_token.refresh_token); - memset(&request, 0, sizeof(grpc_httpcli_request)); - request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST; - request.http.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH; - request.http.hdr_count = 1; - request.http.hdrs = &header; - request.handshaker = &grpc_httpcli_ssl; - grpc_httpcli_post(exec_ctx, httpcli_context, pollset, &request, body, - strlen(body), deadline, response_cb, metadata_req); - gpr_free(body); -} - -grpc_call_credentials * -grpc_refresh_token_credentials_create_from_auth_refresh_token( - grpc_auth_refresh_token refresh_token) { - grpc_google_refresh_token_credentials *c; - if (!grpc_auth_refresh_token_is_valid(&refresh_token)) { - gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation"); - return NULL; - } - c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials)); - memset(c, 0, sizeof(grpc_google_refresh_token_credentials)); - init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2); - c->base.base.vtable = &refresh_token_vtable; - c->refresh_token = refresh_token; - return &c->base.base; -} - -grpc_call_credentials *grpc_google_refresh_token_credentials_create( - const char *json_refresh_token, void *reserved) { - GRPC_API_TRACE( - "grpc_refresh_token_credentials_create(json_refresh_token=%s, " - "reserved=%p)", - 2, (json_refresh_token, reserved)); - GPR_ASSERT(reserved == NULL); - return grpc_refresh_token_credentials_create_from_auth_refresh_token( - grpc_auth_refresh_token_create_from_string(json_refresh_token)); -} - -/* -- Metadata-only credentials. -- */ - -static void md_only_test_destruct(grpc_call_credentials *creds) { - grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds; - grpc_credentials_md_store_unref(c->md_store); -} - -static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx, - void *user_data, bool success) { - grpc_credentials_metadata_request *r = - (grpc_credentials_metadata_request *)user_data; - grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds; - r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries, - GRPC_CREDENTIALS_OK); - grpc_credentials_metadata_request_destroy(r); -} - -static void md_only_test_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, - grpc_pollset *pollset, grpc_auth_metadata_context context, - grpc_credentials_metadata_cb cb, void *user_data) { - grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds; - - if (c->is_async) { - grpc_credentials_metadata_request *cb_arg = - grpc_credentials_metadata_request_create(creds, cb, user_data); - grpc_executor_enqueue( - grpc_closure_create(on_simulated_token_fetch_done, cb_arg), true); - } else { - cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK); - } -} - -static grpc_call_credentials_vtable md_only_test_vtable = { - md_only_test_destruct, md_only_test_get_request_metadata}; - -grpc_call_credentials *grpc_md_only_test_credentials_create( - const char *md_key, const char *md_value, int is_async) { - grpc_md_only_test_credentials *c = - gpr_malloc(sizeof(grpc_md_only_test_credentials)); - memset(c, 0, sizeof(grpc_md_only_test_credentials)); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; - c->base.vtable = &md_only_test_vtable; - gpr_ref_init(&c->base.refcount, 1); - c->md_store = grpc_credentials_md_store_create(1); - grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value); - c->is_async = is_async; - return &c->base; -} - -/* -- Oauth2 Access Token credentials. -- */ - -static void access_token_destruct(grpc_call_credentials *creds) { - grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; - grpc_credentials_md_store_unref(c->access_token_md); -} - -static void access_token_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, - grpc_pollset *pollset, grpc_auth_metadata_context context, - grpc_credentials_metadata_cb cb, void *user_data) { - grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; - cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK); -} - -static grpc_call_credentials_vtable access_token_vtable = { - access_token_destruct, access_token_get_request_metadata}; - -grpc_call_credentials *grpc_access_token_credentials_create( - const char *access_token, void *reserved) { - grpc_access_token_credentials *c = - gpr_malloc(sizeof(grpc_access_token_credentials)); - char *token_md_value; - GRPC_API_TRACE( - "grpc_access_token_credentials_create(access_token=%s, " - "reserved=%p)", - 2, (access_token, reserved)); - GPR_ASSERT(reserved == NULL); - memset(c, 0, sizeof(grpc_access_token_credentials)); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; - c->base.vtable = &access_token_vtable; - gpr_ref_init(&c->base.refcount, 1); - c->access_token_md = grpc_credentials_md_store_create(1); - gpr_asprintf(&token_md_value, "Bearer %s", access_token); - grpc_credentials_md_store_add_cstrings( - c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value); - gpr_free(token_md_value); - return &c->base; -} - -/* -- Fake transport security credentials. -- */ - -static grpc_security_status fake_transport_security_create_security_connector( - grpc_channel_credentials *c, grpc_call_credentials *call_creds, - const char *target, const grpc_channel_args *args, - grpc_channel_security_connector **sc, grpc_channel_args **new_args) { - *sc = grpc_fake_channel_security_connector_create(call_creds); - return GRPC_SECURITY_OK; -} - -static grpc_security_status -fake_transport_security_server_create_security_connector( - grpc_server_credentials *c, grpc_server_security_connector **sc) { - *sc = grpc_fake_server_security_connector_create(); - return GRPC_SECURITY_OK; -} - -static grpc_channel_credentials_vtable - fake_transport_security_credentials_vtable = { - NULL, fake_transport_security_create_security_connector}; - -static grpc_server_credentials_vtable - fake_transport_security_server_credentials_vtable = { - NULL, fake_transport_security_server_create_security_connector}; - -grpc_channel_credentials *grpc_fake_transport_security_credentials_create( - void) { - grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials)); - memset(c, 0, sizeof(grpc_channel_credentials)); - c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; - c->vtable = &fake_transport_security_credentials_vtable; - gpr_ref_init(&c->refcount, 1); - return c; -} - -grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( - void) { - grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials)); - memset(c, 0, sizeof(grpc_server_credentials)); - c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; - gpr_ref_init(&c->refcount, 1); - c->vtable = &fake_transport_security_server_credentials_vtable; - return c; -} - -/* -- Composite call credentials. -- */ - -typedef struct { - grpc_composite_call_credentials *composite_creds; - size_t creds_index; - grpc_credentials_md_store *md_elems; - grpc_auth_metadata_context auth_md_context; - void *user_data; - grpc_pollset *pollset; - grpc_credentials_metadata_cb cb; -} grpc_composite_call_credentials_metadata_context; - -static void composite_call_destruct(grpc_call_credentials *creds) { - grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds; - size_t i; - for (i = 0; i < c->inner.num_creds; i++) { - grpc_call_credentials_unref(c->inner.creds_array[i]); - } - gpr_free(c->inner.creds_array); -} - -static void composite_call_md_context_destroy( - grpc_composite_call_credentials_metadata_context *ctx) { - grpc_credentials_md_store_unref(ctx->md_elems); - gpr_free(ctx); -} - -static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_credentials_md *md_elems, - size_t num_md, - grpc_credentials_status status) { - grpc_composite_call_credentials_metadata_context *ctx = - (grpc_composite_call_credentials_metadata_context *)user_data; - if (status != GRPC_CREDENTIALS_OK) { - ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status); - return; - } - - /* Copy the metadata in the context. */ - if (num_md > 0) { - size_t i; - for (i = 0; i < num_md; i++) { - grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key, - md_elems[i].value); - } - } - - /* See if we need to get some more metadata. */ - if (ctx->creds_index < ctx->composite_creds->inner.num_creds) { - grpc_call_credentials *inner_creds = - ctx->composite_creds->inner.creds_array[ctx->creds_index++]; - grpc_call_credentials_get_request_metadata( - exec_ctx, inner_creds, ctx->pollset, ctx->auth_md_context, - composite_call_metadata_cb, ctx); - return; - } - - /* We're done!. */ - ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries, - ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK); - composite_call_md_context_destroy(ctx); -} - -static void composite_call_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, - grpc_pollset *pollset, grpc_auth_metadata_context auth_md_context, - grpc_credentials_metadata_cb cb, void *user_data) { - grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds; - grpc_composite_call_credentials_metadata_context *ctx; - - ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context)); - memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context)); - ctx->auth_md_context = auth_md_context; - ctx->user_data = user_data; - ctx->cb = cb; - ctx->composite_creds = c; - ctx->pollset = pollset; - ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds); - grpc_call_credentials_get_request_metadata( - exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset, - auth_md_context, composite_call_metadata_cb, ctx); -} - -static grpc_call_credentials_vtable composite_call_credentials_vtable = { - composite_call_destruct, composite_call_get_request_metadata}; - -static grpc_call_credentials_array get_creds_array( - grpc_call_credentials **creds_addr) { - grpc_call_credentials_array result; - grpc_call_credentials *creds = *creds_addr; - result.creds_array = creds_addr; - result.num_creds = 1; - if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) { - result = *grpc_composite_call_credentials_get_credentials(creds); - } - return result; -} - -grpc_call_credentials *grpc_composite_call_credentials_create( - grpc_call_credentials *creds1, grpc_call_credentials *creds2, - void *reserved) { - size_t i; - size_t creds_array_byte_size; - grpc_call_credentials_array creds1_array; - grpc_call_credentials_array creds2_array; - grpc_composite_call_credentials *c; - GRPC_API_TRACE( - "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, " - "reserved=%p)", - 3, (creds1, creds2, reserved)); - GPR_ASSERT(reserved == NULL); - GPR_ASSERT(creds1 != NULL); - GPR_ASSERT(creds2 != NULL); - c = gpr_malloc(sizeof(grpc_composite_call_credentials)); - memset(c, 0, sizeof(grpc_composite_call_credentials)); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE; - c->base.vtable = &composite_call_credentials_vtable; - gpr_ref_init(&c->base.refcount, 1); - creds1_array = get_creds_array(&creds1); - creds2_array = get_creds_array(&creds2); - c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds; - creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *); - c->inner.creds_array = gpr_malloc(creds_array_byte_size); - memset(c->inner.creds_array, 0, creds_array_byte_size); - for (i = 0; i < creds1_array.num_creds; i++) { - grpc_call_credentials *cur_creds = creds1_array.creds_array[i]; - c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds); - } - for (i = 0; i < creds2_array.num_creds; i++) { - grpc_call_credentials *cur_creds = creds2_array.creds_array[i]; - c->inner.creds_array[i + creds1_array.num_creds] = - grpc_call_credentials_ref(cur_creds); - } - return &c->base; -} - -const grpc_call_credentials_array * -grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) { - const grpc_composite_call_credentials *c = - (const grpc_composite_call_credentials *)creds; - GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0); - return &c->inner; -} - -grpc_call_credentials *grpc_credentials_contains_type( - grpc_call_credentials *creds, const char *type, - grpc_call_credentials **composite_creds) { - size_t i; - if (strcmp(creds->type, type) == 0) { - if (composite_creds != NULL) *composite_creds = NULL; - return creds; - } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) { - const grpc_call_credentials_array *inner_creds_array = - grpc_composite_call_credentials_get_credentials(creds); - for (i = 0; i < inner_creds_array->num_creds; i++) { - if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) { - if (composite_creds != NULL) *composite_creds = creds; - return inner_creds_array->creds_array[i]; - } - } - } - return NULL; -} - -/* -- IAM credentials. -- */ - -static void iam_destruct(grpc_call_credentials *creds) { - grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; - grpc_credentials_md_store_unref(c->iam_md); -} - -static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx, - grpc_call_credentials *creds, - grpc_pollset *pollset, - grpc_auth_metadata_context context, - grpc_credentials_metadata_cb cb, - void *user_data) { - grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; - cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries, - GRPC_CREDENTIALS_OK); -} - -static grpc_call_credentials_vtable iam_vtable = {iam_destruct, - iam_get_request_metadata}; - -grpc_call_credentials *grpc_google_iam_credentials_create( - const char *token, const char *authority_selector, void *reserved) { - grpc_google_iam_credentials *c; - GRPC_API_TRACE( - "grpc_iam_credentials_create(token=%s, authority_selector=%s, " - "reserved=%p)", - 3, (token, authority_selector, reserved)); - GPR_ASSERT(reserved == NULL); - GPR_ASSERT(token != NULL); - GPR_ASSERT(authority_selector != NULL); - c = gpr_malloc(sizeof(grpc_google_iam_credentials)); - memset(c, 0, sizeof(grpc_google_iam_credentials)); - c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM; - c->base.vtable = &iam_vtable; - gpr_ref_init(&c->base.refcount, 1); - c->iam_md = grpc_credentials_md_store_create(2); - grpc_credentials_md_store_add_cstrings( - c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token); - grpc_credentials_md_store_add_cstrings( - c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector); - return &c->base; -} - -/* -- Plugin credentials. -- */ - -typedef struct { - void *user_data; - grpc_credentials_metadata_cb cb; -} grpc_metadata_plugin_request; - -static void plugin_destruct(grpc_call_credentials *creds) { - grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds; - if (c->plugin.state != NULL && c->plugin.destroy != NULL) { - c->plugin.destroy(c->plugin.state); - } -} - -static void plugin_md_request_metadata_ready(void *request, - const grpc_metadata *md, - size_t num_md, - grpc_status_code status, - const char *error_details) { - /* called from application code */ - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request; - if (status != GRPC_STATUS_OK) { - if (error_details != NULL) { - gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s", - error_details); - } - r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); - } else { - size_t i; - grpc_credentials_md *md_array = NULL; - if (num_md > 0) { - md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md)); - for (i = 0; i < num_md; i++) { - md_array[i].key = gpr_slice_from_copied_string(md[i].key); - md_array[i].value = - gpr_slice_from_copied_buffer(md[i].value, md[i].value_length); - } - } - r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK); - if (md_array != NULL) { - for (i = 0; i < num_md; i++) { - gpr_slice_unref(md_array[i].key); - gpr_slice_unref(md_array[i].value); - } - gpr_free(md_array); - } - } - gpr_free(r); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx, - grpc_call_credentials *creds, - grpc_pollset *pollset, - grpc_auth_metadata_context context, - grpc_credentials_metadata_cb cb, - void *user_data) { - grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds; - if (c->plugin.get_metadata != NULL) { - grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request)); - memset(request, 0, sizeof(*request)); - request->user_data = user_data; - request->cb = cb; - c->plugin.get_metadata(c->plugin.state, context, - plugin_md_request_metadata_ready, request); - } else { - cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK); - } -} - -static grpc_call_credentials_vtable plugin_vtable = { - plugin_destruct, plugin_get_request_metadata}; - -grpc_call_credentials *grpc_metadata_credentials_create_from_plugin( - grpc_metadata_credentials_plugin plugin, void *reserved) { - grpc_plugin_credentials *c = gpr_malloc(sizeof(*c)); - GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1, - (reserved)); - GPR_ASSERT(reserved == NULL); - memset(c, 0, sizeof(*c)); - c->base.type = plugin.type; - c->base.vtable = &plugin_vtable; - gpr_ref_init(&c->base.refcount, 1); - c->plugin = plugin; - return &c->base; -} - -/* -- Composite channel credentials. -- */ - -static void composite_channel_destruct(grpc_channel_credentials *creds) { - grpc_composite_channel_credentials *c = - (grpc_composite_channel_credentials *)creds; - grpc_channel_credentials_unref(c->inner_creds); - grpc_call_credentials_unref(c->call_creds); -} - -static grpc_security_status composite_channel_create_security_connector( - grpc_channel_credentials *creds, grpc_call_credentials *call_creds, - const char *target, const grpc_channel_args *args, - grpc_channel_security_connector **sc, grpc_channel_args **new_args) { - grpc_composite_channel_credentials *c = - (grpc_composite_channel_credentials *)creds; - grpc_security_status status = GRPC_SECURITY_ERROR; - - GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL && - c->inner_creds->vtable != NULL && - c->inner_creds->vtable->create_security_connector != NULL); - /* If we are passed a call_creds, create a call composite to pass it - downstream. */ - if (call_creds != NULL) { - grpc_call_credentials *composite_call_creds = - grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL); - status = c->inner_creds->vtable->create_security_connector( - c->inner_creds, composite_call_creds, target, args, sc, new_args); - grpc_call_credentials_unref(composite_call_creds); - } else { - status = c->inner_creds->vtable->create_security_connector( - c->inner_creds, c->call_creds, target, args, sc, new_args); - } - return status; -} - -static grpc_channel_credentials_vtable composite_channel_credentials_vtable = { - composite_channel_destruct, composite_channel_create_security_connector}; - -grpc_channel_credentials *grpc_composite_channel_credentials_create( - grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds, - void *reserved) { - grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c)); - memset(c, 0, sizeof(*c)); - GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL); - GRPC_API_TRACE( - "grpc_composite_channel_credentials_create(channel_creds=%p, " - "call_creds=%p, reserved=%p)", - 3, (channel_creds, call_creds, reserved)); - c->base.type = channel_creds->type; - c->base.vtable = &composite_channel_credentials_vtable; - gpr_ref_init(&c->base.refcount, 1); - c->inner_creds = grpc_channel_credentials_ref(channel_creds); - c->call_creds = grpc_call_credentials_ref(call_creds); - return &c->base; -} diff --git a/src/core/lib/security/credentials.h b/src/core/lib/security/credentials.h deleted file mode 100644 index 0373ceaa3f..0000000000 --- a/src/core/lib/security/credentials.h +++ /dev/null @@ -1,377 +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. - * - */ - -#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_H -#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_H - -#include -#include -#include -#include "src/core/lib/transport/metadata_batch.h" - -#include "src/core/lib/http/httpcli.h" -#include "src/core/lib/http/parser.h" -#include "src/core/lib/security/json_token.h" -#include "src/core/lib/security/security_connector.h" - -struct grpc_http_response; - -/* --- Constants. --- */ - -typedef enum { - GRPC_CREDENTIALS_OK = 0, - GRPC_CREDENTIALS_ERROR -} grpc_credentials_status; - -#define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake" - -#define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl" -#define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \ - "FakeTransportSecurity" - -#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2" -#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt" -#define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam" -#define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite" - -#define GRPC_AUTHORIZATION_METADATA_KEY "authorization" -#define GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY \ - "x-goog-iam-authorization-token" -#define GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY "x-goog-iam-authority-selector" - -#define GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY "gcloud" -#define GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE \ - "application_default_credentials.json" - -#define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60 - -#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata" -#define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \ - "/computeMetadata/v1/instance/service-accounts/default/token" - -#define GRPC_GOOGLE_OAUTH2_SERVICE_HOST "www.googleapis.com" -#define GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH "/oauth2/v3/token" - -#define GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX \ - "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" \ - "assertion=" - -#define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \ - "client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token" - -/* --- Google utils --- */ - -/* It is the caller's responsibility to gpr_free the result if not NULL. */ -char *grpc_get_well_known_google_credentials_file_path(void); - -/* Implementation function for the different platforms. */ -char *grpc_get_well_known_google_credentials_file_path_impl(void); - -/* Override for testing only. Not thread-safe */ -typedef char *(*grpc_well_known_credentials_path_getter)(void); -void grpc_override_well_known_credentials_path_getter( - grpc_well_known_credentials_path_getter getter); - -/* --- grpc_channel_credentials. --- */ - -typedef struct { - void (*destruct)(grpc_channel_credentials *c); - - grpc_security_status (*create_security_connector)( - grpc_channel_credentials *c, grpc_call_credentials *call_creds, - const char *target, const grpc_channel_args *args, - grpc_channel_security_connector **sc, grpc_channel_args **new_args); -} grpc_channel_credentials_vtable; - -struct grpc_channel_credentials { - const grpc_channel_credentials_vtable *vtable; - const char *type; - gpr_refcount refcount; -}; - -grpc_channel_credentials *grpc_channel_credentials_ref( - grpc_channel_credentials *creds); -void grpc_channel_credentials_unref(grpc_channel_credentials *creds); - -/* Creates a security connector for the channel. May also create new channel - args for the channel to be used in place of the passed in const args if - returned non NULL. In that case the caller is responsible for destroying - new_args after channel creation. */ -grpc_security_status grpc_channel_credentials_create_security_connector( - grpc_channel_credentials *creds, const char *target, - const grpc_channel_args *args, grpc_channel_security_connector **sc, - grpc_channel_args **new_args); - -/* --- grpc_credentials_md. --- */ - -typedef struct { - gpr_slice key; - gpr_slice value; -} grpc_credentials_md; - -typedef struct { - grpc_credentials_md *entries; - size_t num_entries; - size_t allocated; - gpr_refcount refcount; -} grpc_credentials_md_store; - -grpc_credentials_md_store *grpc_credentials_md_store_create( - size_t initial_capacity); - -/* Will ref key and value. */ -void grpc_credentials_md_store_add(grpc_credentials_md_store *store, - gpr_slice key, gpr_slice value); -void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store, - const char *key, const char *value); -grpc_credentials_md_store *grpc_credentials_md_store_ref( - grpc_credentials_md_store *store); -void grpc_credentials_md_store_unref(grpc_credentials_md_store *store); - -/* --- grpc_call_credentials. --- */ - -typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx, - void *user_data, - grpc_credentials_md *md_elems, - size_t num_md, - grpc_credentials_status status); - -typedef struct { - void (*destruct)(grpc_call_credentials *c); - void (*get_request_metadata)(grpc_exec_ctx *exec_ctx, - grpc_call_credentials *c, grpc_pollset *pollset, - grpc_auth_metadata_context context, - grpc_credentials_metadata_cb cb, - void *user_data); -} grpc_call_credentials_vtable; - -struct grpc_call_credentials { - const grpc_call_credentials_vtable *vtable; - const char *type; - gpr_refcount refcount; -}; - -grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds); -void grpc_call_credentials_unref(grpc_call_credentials *creds); -void grpc_call_credentials_get_request_metadata( - grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, - grpc_pollset *pollset, grpc_auth_metadata_context context, - grpc_credentials_metadata_cb cb, void *user_data); - -typedef struct { - grpc_call_credentials **creds_array; - size_t num_creds; -} grpc_call_credentials_array; - -const grpc_call_credentials_array * -grpc_composite_call_credentials_get_credentials( - grpc_call_credentials *composite_creds); - -/* Returns creds if creds is of the specified type or the inner creds of the - specified type (if found), if the creds is of type COMPOSITE. - If composite_creds is not NULL, *composite_creds will point to creds if of - type COMPOSITE in case of success. */ -grpc_call_credentials *grpc_credentials_contains_type( - grpc_call_credentials *creds, const char *type, - grpc_call_credentials **composite_creds); - -/* Exposed for testing only. */ -grpc_credentials_status -grpc_oauth2_token_fetcher_credentials_parse_server_response( - const struct grpc_http_response *response, - grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime); - -void grpc_flush_cached_google_default_credentials(void); - -/* Metadata-only credentials with the specified key and value where - asynchronicity can be simulated for testing. */ -grpc_call_credentials *grpc_md_only_test_credentials_create( - const char *md_key, const char *md_value, int is_async); - -/* Private constructor for jwt credentials from an already parsed json key. - Takes ownership of the key. */ -grpc_call_credentials * -grpc_service_account_jwt_access_credentials_create_from_auth_json_key( - grpc_auth_json_key key, gpr_timespec token_lifetime); - -/* Private constructor for refresh token credentials from an already parsed - refresh token. Takes ownership of the refresh token. */ -grpc_call_credentials * -grpc_refresh_token_credentials_create_from_auth_refresh_token( - grpc_auth_refresh_token token); - -/* --- grpc_server_credentials. --- */ - -typedef struct { - void (*destruct)(grpc_server_credentials *c); - grpc_security_status (*create_security_connector)( - grpc_server_credentials *c, grpc_server_security_connector **sc); -} grpc_server_credentials_vtable; - -struct grpc_server_credentials { - const grpc_server_credentials_vtable *vtable; - const char *type; - gpr_refcount refcount; - grpc_auth_metadata_processor processor; -}; - -grpc_security_status grpc_server_credentials_create_security_connector( - grpc_server_credentials *creds, grpc_server_security_connector **sc); - -grpc_server_credentials *grpc_server_credentials_ref( - grpc_server_credentials *creds); - -void grpc_server_credentials_unref(grpc_server_credentials *creds); - -#define GRPC_SERVER_CREDENTIALS_ARG "grpc.server_credentials" - -grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *c); -grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg); -grpc_server_credentials *grpc_find_server_credentials_in_args( - const grpc_channel_args *args); - -/* -- Fake transport security credentials. -- */ - -/* Creates a fake transport security credentials object for testing. */ -grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void); -/* Creates a fake server transport security credentials object for testing. */ -grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( - void); - -/* -- Ssl credentials. -- */ - -typedef struct { - grpc_channel_credentials base; - grpc_ssl_config config; -} grpc_ssl_credentials; - -typedef struct { - grpc_server_credentials base; - grpc_ssl_server_config config; -} grpc_ssl_server_credentials; - -/* -- Channel composite credentials. -- */ - -typedef struct { - grpc_channel_credentials base; - grpc_channel_credentials *inner_creds; - grpc_call_credentials *call_creds; -} grpc_composite_channel_credentials; - -/* -- Jwt credentials -- */ - -typedef struct { - grpc_call_credentials base; - - /* Have a simple cache for now with just 1 entry. We could have a map based on - the service_url for a more sophisticated one. */ - gpr_mu cache_mu; - struct { - grpc_credentials_md_store *jwt_md; - char *service_url; - gpr_timespec jwt_expiration; - } cached; - - grpc_auth_json_key key; - gpr_timespec jwt_lifetime; -} grpc_service_account_jwt_access_credentials; - -/* -- Oauth2TokenFetcher credentials -- - - This object is a base for credentials that need to acquire an oauth2 token - from an http service. */ - -typedef struct grpc_credentials_metadata_request - grpc_credentials_metadata_request; - -typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx, - grpc_credentials_metadata_request *req, - grpc_httpcli_context *http_context, - grpc_pollset *pollset, - grpc_httpcli_response_cb response_cb, - gpr_timespec deadline); - -typedef struct { - grpc_call_credentials base; - gpr_mu mu; - grpc_credentials_md_store *access_token_md; - gpr_timespec token_expiration; - grpc_httpcli_context httpcli_context; - grpc_fetch_oauth2_func fetch_func; -} grpc_oauth2_token_fetcher_credentials; - -/* -- GoogleRefreshToken credentials. -- */ - -typedef struct { - grpc_oauth2_token_fetcher_credentials base; - grpc_auth_refresh_token refresh_token; -} grpc_google_refresh_token_credentials; - -/* -- Oauth2 Access Token credentials. -- */ - -typedef struct { - grpc_call_credentials base; - grpc_credentials_md_store *access_token_md; -} grpc_access_token_credentials; - -/* -- Metadata-only Test credentials. -- */ - -typedef struct { - grpc_call_credentials base; - grpc_credentials_md_store *md_store; - int is_async; -} grpc_md_only_test_credentials; - -/* -- GoogleIAM credentials. -- */ - -typedef struct { - grpc_call_credentials base; - grpc_credentials_md_store *iam_md; -} grpc_google_iam_credentials; - -/* -- Composite credentials. -- */ - -typedef struct { - grpc_call_credentials base; - grpc_call_credentials_array inner; -} grpc_composite_call_credentials; - -/* -- Plugin credentials. -- */ - -typedef struct { - grpc_call_credentials base; - grpc_metadata_credentials_plugin plugin; - grpc_credentials_md_store *plugin_md; -} grpc_plugin_credentials; - -#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_H */ diff --git a/src/core/lib/security/credentials/composite/composite_credentials.c b/src/core/lib/security/credentials/composite/composite_credentials.c new file mode 100644 index 0000000000..4a17f7c1b9 --- /dev/null +++ b/src/core/lib/security/credentials/composite/composite_credentials.c @@ -0,0 +1,263 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/composite/composite_credentials.h" + +#include + +#include "src/core/lib/surface/api_trace.h" + +#include +#include +#include + +/* -- Composite call credentials. -- */ + +typedef struct { + grpc_composite_call_credentials *composite_creds; + size_t creds_index; + grpc_credentials_md_store *md_elems; + grpc_auth_metadata_context auth_md_context; + void *user_data; + grpc_pollset *pollset; + grpc_credentials_metadata_cb cb; +} grpc_composite_call_credentials_metadata_context; + +static void composite_call_destruct(grpc_call_credentials *creds) { + grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds; + size_t i; + for (i = 0; i < c->inner.num_creds; i++) { + grpc_call_credentials_unref(c->inner.creds_array[i]); + } + gpr_free(c->inner.creds_array); +} + +static void composite_call_md_context_destroy( + grpc_composite_call_credentials_metadata_context *ctx) { + grpc_credentials_md_store_unref(ctx->md_elems); + gpr_free(ctx); +} + +static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_credentials_md *md_elems, + size_t num_md, + grpc_credentials_status status) { + grpc_composite_call_credentials_metadata_context *ctx = + (grpc_composite_call_credentials_metadata_context *)user_data; + if (status != GRPC_CREDENTIALS_OK) { + ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status); + return; + } + + /* Copy the metadata in the context. */ + if (num_md > 0) { + size_t i; + for (i = 0; i < num_md; i++) { + grpc_credentials_md_store_add(ctx->md_elems, md_elems[i].key, + md_elems[i].value); + } + } + + /* See if we need to get some more metadata. */ + if (ctx->creds_index < ctx->composite_creds->inner.num_creds) { + grpc_call_credentials *inner_creds = + ctx->composite_creds->inner.creds_array[ctx->creds_index++]; + grpc_call_credentials_get_request_metadata( + exec_ctx, inner_creds, ctx->pollset, ctx->auth_md_context, + composite_call_metadata_cb, ctx); + return; + } + + /* We're done!. */ + ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries, + ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK); + composite_call_md_context_destroy(ctx); +} + +static void composite_call_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, + grpc_pollset *pollset, grpc_auth_metadata_context auth_md_context, + grpc_credentials_metadata_cb cb, void *user_data) { + grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds; + grpc_composite_call_credentials_metadata_context *ctx; + + ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context)); + memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context)); + ctx->auth_md_context = auth_md_context; + ctx->user_data = user_data; + ctx->cb = cb; + ctx->composite_creds = c; + ctx->pollset = pollset; + ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds); + grpc_call_credentials_get_request_metadata( + exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset, + auth_md_context, composite_call_metadata_cb, ctx); +} + +static grpc_call_credentials_vtable composite_call_credentials_vtable = { + composite_call_destruct, composite_call_get_request_metadata}; + +static grpc_call_credentials_array get_creds_array( + grpc_call_credentials **creds_addr) { + grpc_call_credentials_array result; + grpc_call_credentials *creds = *creds_addr; + result.creds_array = creds_addr; + result.num_creds = 1; + if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) { + result = *grpc_composite_call_credentials_get_credentials(creds); + } + return result; +} + +grpc_call_credentials *grpc_composite_call_credentials_create( + grpc_call_credentials *creds1, grpc_call_credentials *creds2, + void *reserved) { + size_t i; + size_t creds_array_byte_size; + grpc_call_credentials_array creds1_array; + grpc_call_credentials_array creds2_array; + grpc_composite_call_credentials *c; + GRPC_API_TRACE( + "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, " + "reserved=%p)", + 3, (creds1, creds2, reserved)); + GPR_ASSERT(reserved == NULL); + GPR_ASSERT(creds1 != NULL); + GPR_ASSERT(creds2 != NULL); + c = gpr_malloc(sizeof(grpc_composite_call_credentials)); + memset(c, 0, sizeof(grpc_composite_call_credentials)); + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE; + c->base.vtable = &composite_call_credentials_vtable; + gpr_ref_init(&c->base.refcount, 1); + creds1_array = get_creds_array(&creds1); + creds2_array = get_creds_array(&creds2); + c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds; + creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *); + c->inner.creds_array = gpr_malloc(creds_array_byte_size); + memset(c->inner.creds_array, 0, creds_array_byte_size); + for (i = 0; i < creds1_array.num_creds; i++) { + grpc_call_credentials *cur_creds = creds1_array.creds_array[i]; + c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds); + } + for (i = 0; i < creds2_array.num_creds; i++) { + grpc_call_credentials *cur_creds = creds2_array.creds_array[i]; + c->inner.creds_array[i + creds1_array.num_creds] = + grpc_call_credentials_ref(cur_creds); + } + return &c->base; +} + +const grpc_call_credentials_array * +grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) { + const grpc_composite_call_credentials *c = + (const grpc_composite_call_credentials *)creds; + GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0); + return &c->inner; +} + +grpc_call_credentials *grpc_credentials_contains_type( + grpc_call_credentials *creds, const char *type, + grpc_call_credentials **composite_creds) { + size_t i; + if (strcmp(creds->type, type) == 0) { + if (composite_creds != NULL) *composite_creds = NULL; + return creds; + } else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) { + const grpc_call_credentials_array *inner_creds_array = + grpc_composite_call_credentials_get_credentials(creds); + for (i = 0; i < inner_creds_array->num_creds; i++) { + if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) { + if (composite_creds != NULL) *composite_creds = creds; + return inner_creds_array->creds_array[i]; + } + } + } + return NULL; +} + +/* -- Composite channel credentials. -- */ + +static void composite_channel_destruct(grpc_channel_credentials *creds) { + grpc_composite_channel_credentials *c = + (grpc_composite_channel_credentials *)creds; + grpc_channel_credentials_unref(c->inner_creds); + grpc_call_credentials_unref(c->call_creds); +} + +static grpc_security_status composite_channel_create_security_connector( + grpc_channel_credentials *creds, grpc_call_credentials *call_creds, + const char *target, const grpc_channel_args *args, + grpc_channel_security_connector **sc, grpc_channel_args **new_args) { + grpc_composite_channel_credentials *c = + (grpc_composite_channel_credentials *)creds; + grpc_security_status status = GRPC_SECURITY_ERROR; + + GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL && + c->inner_creds->vtable != NULL && + c->inner_creds->vtable->create_security_connector != NULL); + /* If we are passed a call_creds, create a call composite to pass it + downstream. */ + if (call_creds != NULL) { + grpc_call_credentials *composite_call_creds = + grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL); + status = c->inner_creds->vtable->create_security_connector( + c->inner_creds, composite_call_creds, target, args, sc, new_args); + grpc_call_credentials_unref(composite_call_creds); + } else { + status = c->inner_creds->vtable->create_security_connector( + c->inner_creds, c->call_creds, target, args, sc, new_args); + } + return status; +} + +static grpc_channel_credentials_vtable composite_channel_credentials_vtable = { + composite_channel_destruct, composite_channel_create_security_connector}; + +grpc_channel_credentials *grpc_composite_channel_credentials_create( + grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds, + void *reserved) { + grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL); + GRPC_API_TRACE( + "grpc_composite_channel_credentials_create(channel_creds=%p, " + "call_creds=%p, reserved=%p)", + 3, (channel_creds, call_creds, reserved)); + c->base.type = channel_creds->type; + c->base.vtable = &composite_channel_credentials_vtable; + gpr_ref_init(&c->base.refcount, 1); + c->inner_creds = grpc_channel_credentials_ref(channel_creds); + c->call_creds = grpc_call_credentials_ref(call_creds); + return &c->base; +} + diff --git a/src/core/lib/security/credentials/composite/composite_credentials.h b/src/core/lib/security/credentials/composite/composite_credentials.h new file mode 100644 index 0000000000..c83f74429f --- /dev/null +++ b/src/core/lib/security/credentials/composite/composite_credentials.h @@ -0,0 +1,72 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_COMPOSITE_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_COMPOSITE_CREDENTIALS_H + +#include "src/core/lib/security/credentials/credentials.h" + +typedef struct { + grpc_call_credentials **creds_array; + size_t num_creds; +} grpc_call_credentials_array; + +const grpc_call_credentials_array * +grpc_composite_call_credentials_get_credentials( + grpc_call_credentials *composite_creds); + +/* Returns creds if creds is of the specified type or the inner creds of the + specified type (if found), if the creds is of type COMPOSITE. + If composite_creds is not NULL, *composite_creds will point to creds if of + type COMPOSITE in case of success. */ +grpc_call_credentials *grpc_credentials_contains_type( + grpc_call_credentials *creds, const char *type, + grpc_call_credentials **composite_creds); + +/* -- Channel composite credentials. -- */ + +typedef struct { + grpc_channel_credentials base; + grpc_channel_credentials *inner_creds; + grpc_call_credentials *call_creds; +} grpc_composite_channel_credentials; + +/* -- Composite credentials. -- */ + +typedef struct { + grpc_call_credentials base; + grpc_call_credentials_array inner; +} grpc_composite_call_credentials; + +#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_COMPOSITE_CREDENTIALS_H + diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c new file mode 100644 index 0000000000..29cf9ee884 --- /dev/null +++ b/src/core/lib/security/credentials/credentials.c @@ -0,0 +1,233 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/credentials.h" + +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/http_client_filter.h" +#include "src/core/lib/http/httpcli.h" +#include "src/core/lib/http/parser.h" +#include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/json/json.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/api_trace.h" + +#include +#include +#include +#include +#include + +/* -- Common. -- */ + +grpc_credentials_metadata_request * +grpc_credentials_metadata_request_create(grpc_call_credentials *creds, + grpc_credentials_metadata_cb cb, + void *user_data) { + grpc_credentials_metadata_request *r = + gpr_malloc(sizeof(grpc_credentials_metadata_request)); + r->creds = grpc_call_credentials_ref(creds); + r->cb = cb; + r->user_data = user_data; + return r; +} + +void grpc_credentials_metadata_request_destroy( + grpc_credentials_metadata_request *r) { + grpc_call_credentials_unref(r->creds); + gpr_free(r); +} + +grpc_channel_credentials *grpc_channel_credentials_ref( + grpc_channel_credentials *creds) { + if (creds == NULL) return NULL; + gpr_ref(&creds->refcount); + return creds; +} + +void grpc_channel_credentials_unref(grpc_channel_credentials *creds) { + if (creds == NULL) return; + if (gpr_unref(&creds->refcount)) { + if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds); + gpr_free(creds); + } +} + +void grpc_channel_credentials_release(grpc_channel_credentials *creds) { + GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds)); + grpc_channel_credentials_unref(creds); +} + +grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) { + if (creds == NULL) return NULL; + gpr_ref(&creds->refcount); + return creds; +} + +void grpc_call_credentials_unref(grpc_call_credentials *creds) { + if (creds == NULL) return; + if (gpr_unref(&creds->refcount)) { + if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds); + gpr_free(creds); + } +} + +void grpc_call_credentials_release(grpc_call_credentials *creds) { + GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds)); + grpc_call_credentials_unref(creds); +} + +void grpc_call_credentials_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, + grpc_pollset *pollset, grpc_auth_metadata_context context, + grpc_credentials_metadata_cb cb, void *user_data) { + if (creds == NULL || creds->vtable->get_request_metadata == NULL) { + if (cb != NULL) { + cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK); + } + return; + } + creds->vtable->get_request_metadata(exec_ctx, creds, pollset, context, cb, + user_data); +} + +grpc_security_status grpc_channel_credentials_create_security_connector( + grpc_channel_credentials *channel_creds, const char *target, + const grpc_channel_args *args, grpc_channel_security_connector **sc, + grpc_channel_args **new_args) { + *new_args = NULL; + if (channel_creds == NULL) { + return GRPC_SECURITY_ERROR; + } + GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL); + return channel_creds->vtable->create_security_connector( + channel_creds, NULL, target, args, sc, new_args); +} + +grpc_server_credentials *grpc_server_credentials_ref( + grpc_server_credentials *creds) { + if (creds == NULL) return NULL; + gpr_ref(&creds->refcount); + return creds; +} + +void grpc_server_credentials_unref(grpc_server_credentials *creds) { + if (creds == NULL) return; + if (gpr_unref(&creds->refcount)) { + if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds); + if (creds->processor.destroy != NULL && creds->processor.state != NULL) { + creds->processor.destroy(creds->processor.state); + } + gpr_free(creds); + } +} + +void grpc_server_credentials_release(grpc_server_credentials *creds) { + GRPC_API_TRACE("grpc_server_credentials_release(creds=%p)", 1, (creds)); + grpc_server_credentials_unref(creds); +} + +grpc_security_status grpc_server_credentials_create_security_connector( + grpc_server_credentials *creds, grpc_server_security_connector **sc) { + if (creds == NULL || creds->vtable->create_security_connector == NULL) { + gpr_log(GPR_ERROR, "Server credentials cannot create security context."); + return GRPC_SECURITY_ERROR; + } + return creds->vtable->create_security_connector(creds, sc); +} + +void grpc_server_credentials_set_auth_metadata_processor( + grpc_server_credentials *creds, grpc_auth_metadata_processor processor) { + GRPC_API_TRACE( + "grpc_server_credentials_set_auth_metadata_processor(" + "creds=%p, " + "processor=grpc_auth_metadata_processor { process: %p, state: %p })", + 3, (creds, (void *)(intptr_t)processor.process, processor.state)); + if (creds == NULL) return; + if (creds->processor.destroy != NULL && creds->processor.state != NULL) { + creds->processor.destroy(creds->processor.state); + } + creds->processor = processor; +} + +static void server_credentials_pointer_arg_destroy(void *p) { + grpc_server_credentials_unref(p); +} + +static void *server_credentials_pointer_arg_copy(void *p) { + return grpc_server_credentials_ref(p); +} + +static int server_credentials_pointer_cmp(void *a, void *b) { + return GPR_ICMP(a, b); +} + +static const grpc_arg_pointer_vtable cred_ptr_vtable = { + server_credentials_pointer_arg_copy, server_credentials_pointer_arg_destroy, + server_credentials_pointer_cmp}; + +grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *p) { + grpc_arg arg; + memset(&arg, 0, sizeof(grpc_arg)); + arg.type = GRPC_ARG_POINTER; + arg.key = GRPC_SERVER_CREDENTIALS_ARG; + arg.value.pointer.p = p; + arg.value.pointer.vtable = &cred_ptr_vtable; + return arg; +} + +grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg) { + if (strcmp(arg->key, GRPC_SERVER_CREDENTIALS_ARG) != 0) return NULL; + if (arg->type != GRPC_ARG_POINTER) { + gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, + GRPC_SERVER_CREDENTIALS_ARG); + return NULL; + } + return arg->value.pointer.p; +} + +grpc_server_credentials *grpc_find_server_credentials_in_args( + const grpc_channel_args *args) { + size_t i; + if (args == NULL) return NULL; + for (i = 0; i < args->num_args; i++) { + grpc_server_credentials *p = + grpc_server_credentials_from_arg(&args->args[i]); + if (p != NULL) return p; + } + return NULL; +} + diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h new file mode 100644 index 0000000000..5f44c7c3e3 --- /dev/null +++ b/src/core/lib/security/credentials/credentials.h @@ -0,0 +1,236 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H + +#include +#include +#include +#include "src/core/lib/transport/metadata_batch.h" + +#include "src/core/lib/http/httpcli.h" +#include "src/core/lib/http/parser.h" +#include "src/core/lib/security/transport/security_connector.h" + +struct grpc_http_response; + +/* --- Constants. --- */ + +typedef enum { + GRPC_CREDENTIALS_OK = 0, + GRPC_CREDENTIALS_ERROR +} grpc_credentials_status; + +#define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake" + +#define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl" +#define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \ + "FakeTransportSecurity" + +#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2" +#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt" +#define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam" +#define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite" + +#define GRPC_AUTHORIZATION_METADATA_KEY "authorization" +#define GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY \ + "x-goog-iam-authorization-token" +#define GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY "x-goog-iam-authority-selector" + +#define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60 + +#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata" +#define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \ + "/computeMetadata/v1/instance/service-accounts/default/token" + +#define GRPC_GOOGLE_OAUTH2_SERVICE_HOST "www.googleapis.com" +#define GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH "/oauth2/v3/token" + +#define GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX \ + "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" \ + "assertion=" + +#define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \ + "client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token" + +/* --- Google utils --- */ + +/* It is the caller's responsibility to gpr_free the result if not NULL. */ +char *grpc_get_well_known_google_credentials_file_path(void); + +/* Implementation function for the different platforms. */ +char *grpc_get_well_known_google_credentials_file_path_impl(void); + +/* Override for testing only. Not thread-safe */ +typedef char *(*grpc_well_known_credentials_path_getter)(void); +void grpc_override_well_known_credentials_path_getter( + grpc_well_known_credentials_path_getter getter); + +/* --- grpc_channel_credentials. --- */ + +typedef struct { + void (*destruct)(grpc_channel_credentials *c); + + grpc_security_status (*create_security_connector)( + grpc_channel_credentials *c, grpc_call_credentials *call_creds, + const char *target, const grpc_channel_args *args, + grpc_channel_security_connector **sc, grpc_channel_args **new_args); +} grpc_channel_credentials_vtable; + +struct grpc_channel_credentials { + const grpc_channel_credentials_vtable *vtable; + const char *type; + gpr_refcount refcount; +}; + +grpc_channel_credentials *grpc_channel_credentials_ref( + grpc_channel_credentials *creds); +void grpc_channel_credentials_unref(grpc_channel_credentials *creds); + +/* Creates a security connector for the channel. May also create new channel + args for the channel to be used in place of the passed in const args if + returned non NULL. In that case the caller is responsible for destroying + new_args after channel creation. */ +grpc_security_status grpc_channel_credentials_create_security_connector( + grpc_channel_credentials *creds, const char *target, + const grpc_channel_args *args, grpc_channel_security_connector **sc, + grpc_channel_args **new_args); + +/* --- grpc_credentials_md. --- */ + +typedef struct { + gpr_slice key; + gpr_slice value; +} grpc_credentials_md; + +typedef struct { + grpc_credentials_md *entries; + size_t num_entries; + size_t allocated; + gpr_refcount refcount; +} grpc_credentials_md_store; + +grpc_credentials_md_store *grpc_credentials_md_store_create( + size_t initial_capacity); + +/* Will ref key and value. */ +void grpc_credentials_md_store_add(grpc_credentials_md_store *store, + gpr_slice key, gpr_slice value); +void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store, + const char *key, const char *value); +grpc_credentials_md_store *grpc_credentials_md_store_ref( + grpc_credentials_md_store *store); +void grpc_credentials_md_store_unref(grpc_credentials_md_store *store); + +/* --- grpc_call_credentials. --- */ + +typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx, + void *user_data, + grpc_credentials_md *md_elems, + size_t num_md, + grpc_credentials_status status); + +typedef struct { + void (*destruct)(grpc_call_credentials *c); + void (*get_request_metadata)(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *c, grpc_pollset *pollset, + grpc_auth_metadata_context context, + grpc_credentials_metadata_cb cb, + void *user_data); +} grpc_call_credentials_vtable; + +struct grpc_call_credentials { + const grpc_call_credentials_vtable *vtable; + const char *type; + gpr_refcount refcount; +}; + +grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds); +void grpc_call_credentials_unref(grpc_call_credentials *creds); +void grpc_call_credentials_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, + grpc_pollset *pollset, grpc_auth_metadata_context context, + grpc_credentials_metadata_cb cb, void *user_data); + +/* Metadata-only credentials with the specified key and value where + asynchronicity can be simulated for testing. */ +grpc_call_credentials *grpc_md_only_test_credentials_create( + const char *md_key, const char *md_value, int is_async); + +/* --- grpc_server_credentials. --- */ + +typedef struct { + void (*destruct)(grpc_server_credentials *c); + grpc_security_status (*create_security_connector)( + grpc_server_credentials *c, grpc_server_security_connector **sc); +} grpc_server_credentials_vtable; + +struct grpc_server_credentials { + const grpc_server_credentials_vtable *vtable; + const char *type; + gpr_refcount refcount; + grpc_auth_metadata_processor processor; +}; + +grpc_security_status grpc_server_credentials_create_security_connector( + grpc_server_credentials *creds, grpc_server_security_connector **sc); + +grpc_server_credentials *grpc_server_credentials_ref( + grpc_server_credentials *creds); + +void grpc_server_credentials_unref(grpc_server_credentials *creds); + +#define GRPC_SERVER_CREDENTIALS_ARG "grpc.server_credentials" + +grpc_arg grpc_server_credentials_to_arg(grpc_server_credentials *c); +grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg); +grpc_server_credentials *grpc_find_server_credentials_in_args( + const grpc_channel_args *args); + +/* -- Credentials Metadata Request. -- */ + +typedef struct { + grpc_call_credentials *creds; + grpc_credentials_metadata_cb cb; + void *user_data; +} grpc_credentials_metadata_request; + +grpc_credentials_metadata_request *grpc_credentials_metadata_request_create( + grpc_call_credentials *creds, grpc_credentials_metadata_cb cb, + void *user_data); + +void grpc_credentials_metadata_request_destroy( + grpc_credentials_metadata_request *r); + +#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_CREDENTIALS_H */ diff --git a/src/core/lib/security/credentials/credentials_metadata.c b/src/core/lib/security/credentials/credentials_metadata.c new file mode 100644 index 0000000000..6a352aab3a --- /dev/null +++ b/src/core/lib/security/credentials/credentials_metadata.c @@ -0,0 +1,101 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/credentials.h" + +#include + +#include + +static void store_ensure_capacity(grpc_credentials_md_store *store) { + if (store->num_entries == store->allocated) { + store->allocated = (store->allocated == 0) ? 1 : store->allocated * 2; + store->entries = gpr_realloc( + store->entries, store->allocated * sizeof(grpc_credentials_md)); + } +} + +grpc_credentials_md_store *grpc_credentials_md_store_create( + size_t initial_capacity) { + grpc_credentials_md_store *store = + gpr_malloc(sizeof(grpc_credentials_md_store)); + memset(store, 0, sizeof(grpc_credentials_md_store)); + if (initial_capacity > 0) { + store->entries = gpr_malloc(initial_capacity * sizeof(grpc_credentials_md)); + store->allocated = initial_capacity; + } + gpr_ref_init(&store->refcount, 1); + return store; +} + +void grpc_credentials_md_store_add(grpc_credentials_md_store *store, + gpr_slice key, gpr_slice value) { + if (store == NULL) return; + store_ensure_capacity(store); + store->entries[store->num_entries].key = gpr_slice_ref(key); + store->entries[store->num_entries].value = gpr_slice_ref(value); + store->num_entries++; +} + +void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store, + const char *key, + const char *value) { + if (store == NULL) return; + store_ensure_capacity(store); + store->entries[store->num_entries].key = gpr_slice_from_copied_string(key); + store->entries[store->num_entries].value = + gpr_slice_from_copied_string(value); + store->num_entries++; +} + +grpc_credentials_md_store *grpc_credentials_md_store_ref( + grpc_credentials_md_store *store) { + if (store == NULL) return NULL; + gpr_ref(&store->refcount); + return store; +} + +void grpc_credentials_md_store_unref(grpc_credentials_md_store *store) { + if (store == NULL) return; + if (gpr_unref(&store->refcount)) { + if (store->entries != NULL) { + size_t i; + for (i = 0; i < store->num_entries; i++) { + gpr_slice_unref(store->entries[i].key); + gpr_slice_unref(store->entries[i].value); + } + gpr_free(store->entries); + } + gpr_free(store); + } +} diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c new file mode 100644 index 0000000000..2a5d225078 --- /dev/null +++ b/src/core/lib/security/credentials/fake/fake_credentials.c @@ -0,0 +1,139 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/fake/fake_credentials.h" + +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/executor.h" + +#include +#include +#include + +/* -- Fake transport security credentials. -- */ + +static grpc_security_status fake_transport_security_create_security_connector( + grpc_channel_credentials *c, grpc_call_credentials *call_creds, + const char *target, const grpc_channel_args *args, + grpc_channel_security_connector **sc, grpc_channel_args **new_args) { + *sc = grpc_fake_channel_security_connector_create(call_creds); + return GRPC_SECURITY_OK; +} + +static grpc_security_status +fake_transport_security_server_create_security_connector( + grpc_server_credentials *c, grpc_server_security_connector **sc) { + *sc = grpc_fake_server_security_connector_create(); + return GRPC_SECURITY_OK; +} + +static grpc_channel_credentials_vtable + fake_transport_security_credentials_vtable = { + NULL, fake_transport_security_create_security_connector}; + +static grpc_server_credentials_vtable + fake_transport_security_server_credentials_vtable = { + NULL, fake_transport_security_server_create_security_connector}; + +grpc_channel_credentials *grpc_fake_transport_security_credentials_create( + void) { + grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials)); + memset(c, 0, sizeof(grpc_channel_credentials)); + c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; + c->vtable = &fake_transport_security_credentials_vtable; + gpr_ref_init(&c->refcount, 1); + return c; +} + +grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( + void) { + grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials)); + memset(c, 0, sizeof(grpc_server_credentials)); + c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; + gpr_ref_init(&c->refcount, 1); + c->vtable = &fake_transport_security_server_credentials_vtable; + return c; +} + +/* -- Metadata-only test credentials. -- */ + +static void md_only_test_destruct(grpc_call_credentials *creds) { + grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds; + grpc_credentials_md_store_unref(c->md_store); +} + +static void on_simulated_token_fetch_done(grpc_exec_ctx *exec_ctx, + void *user_data, bool success) { + grpc_credentials_metadata_request *r = + (grpc_credentials_metadata_request *)user_data; + grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)r->creds; + r->cb(exec_ctx, r->user_data, c->md_store->entries, c->md_store->num_entries, + GRPC_CREDENTIALS_OK); + grpc_credentials_metadata_request_destroy(r); +} + +static void md_only_test_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, + grpc_pollset *pollset, grpc_auth_metadata_context context, + grpc_credentials_metadata_cb cb, void *user_data) { + grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds; + + if (c->is_async) { + grpc_credentials_metadata_request *cb_arg = + grpc_credentials_metadata_request_create(creds, cb, user_data); + grpc_executor_enqueue( + grpc_closure_create(on_simulated_token_fetch_done, cb_arg), true); + } else { + cb(exec_ctx, user_data, c->md_store->entries, 1, GRPC_CREDENTIALS_OK); + } +} + +static grpc_call_credentials_vtable md_only_test_vtable = { + md_only_test_destruct, md_only_test_get_request_metadata}; + +grpc_call_credentials *grpc_md_only_test_credentials_create( + const char *md_key, const char *md_value, int is_async) { + grpc_md_only_test_credentials *c = + gpr_malloc(sizeof(grpc_md_only_test_credentials)); + memset(c, 0, sizeof(grpc_md_only_test_credentials)); + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; + c->base.vtable = &md_only_test_vtable; + gpr_ref_init(&c->base.refcount, 1); + c->md_store = grpc_credentials_md_store_create(1); + grpc_credentials_md_store_add_cstrings(c->md_store, md_key, md_value); + c->is_async = is_async; + return &c->base; +} + diff --git a/src/core/lib/security/credentials/fake/fake_credentials.h b/src/core/lib/security/credentials/fake/fake_credentials.h new file mode 100644 index 0000000000..10c2a0b5ce --- /dev/null +++ b/src/core/lib/security/credentials/fake/fake_credentials.h @@ -0,0 +1,56 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_CREDENTIALS_H + +#include "src/core/lib/security/credentials/credentials.h" + +/* -- Fake transport security credentials. -- */ + +/* Creates a fake transport security credentials object for testing. */ +grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void); +/* Creates a fake server transport security credentials object for testing. */ +grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( + void); + +/* -- Metadata-only Test credentials. -- */ + +typedef struct { + grpc_call_credentials base; + grpc_credentials_md_store *md_store; + int is_async; +} grpc_md_only_test_credentials; + +#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_FAKE_CREDENTIALS_H + diff --git a/src/core/lib/security/credentials/google_default/credentials_posix.c b/src/core/lib/security/credentials/google_default/credentials_posix.c new file mode 100644 index 0000000000..42c9d7f997 --- /dev/null +++ b/src/core/lib/security/credentials/google_default/credentials_posix.c @@ -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 + +#ifdef GPR_POSIX_FILE + +#include "src/core/lib/security/credentials/google_default/google_default_credentials.h" + +#include +#include +#include + +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" + +char *grpc_get_well_known_google_credentials_file_path_impl(void) { + char *result = NULL; + char *home = gpr_getenv("HOME"); + if (home == NULL) { + gpr_log(GPR_ERROR, "Could not get HOME environment variable."); + return NULL; + } + gpr_asprintf(&result, "%s/.config/%s/%s", home, + GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY, + GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE); + gpr_free(home); + return result; +} + +#endif /* GPR_POSIX_FILE */ diff --git a/src/core/lib/security/credentials/google_default/credentials_win32.c b/src/core/lib/security/credentials/google_default/credentials_win32.c new file mode 100644 index 0000000000..cd8b48080a --- /dev/null +++ b/src/core/lib/security/credentials/google_default/credentials_win32.c @@ -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 + +#ifdef GPR_WIN32 + +#include "src/core/lib/security/credentials/google_default/google_default_credentials.h" + +#include +#include +#include + +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/string.h" + +char *grpc_get_well_known_google_credentials_file_path_impl(void) { + char *result = NULL; + char *appdata_path = gpr_getenv("APPDATA"); + if (appdata_path == NULL) { + gpr_log(GPR_ERROR, "Could not get APPDATA environment variable."); + return NULL; + } + gpr_asprintf(&result, "%s/%s/%s", appdata_path, + GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY, + GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE); + gpr_free(appdata_path); + return result; +} + +#endif /* GPR_WIN32 */ diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.c b/src/core/lib/security/credentials/google_default/google_default_credentials.c new file mode 100644 index 0000000000..da23bba62b --- /dev/null +++ b/src/core/lib/security/credentials/google_default/google_default_credentials.c @@ -0,0 +1,268 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/credentials.h" + +#include + +#include +#include +#include + +#include "src/core/lib/http/httpcli.h" +#include "src/core/lib/http/parser.h" +#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" +#include "src/core/lib/security/credentials/jwt/jwt_credentials.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/load_file.h" +#include "src/core/lib/surface/api_trace.h" + +/* -- Constants. -- */ + +#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" + +/* -- Default credentials. -- */ + +static grpc_channel_credentials *default_credentials = NULL; +static int compute_engine_detection_done = 0; +static gpr_mu g_state_mu; +static gpr_mu *g_polling_mu; +static gpr_once g_once = GPR_ONCE_INIT; + +static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); } + +typedef struct { + grpc_pollset *pollset; + int is_done; + int success; +} compute_engine_detector; + +static void on_compute_engine_detection_http_response( + grpc_exec_ctx *exec_ctx, void *user_data, + const grpc_http_response *response) { + compute_engine_detector *detector = (compute_engine_detector *)user_data; + if (response != NULL && response->status == 200 && response->hdr_count > 0) { + /* Internet providers can return a generic response to all requests, so + it is necessary to check that metadata header is present also. */ + size_t i; + for (i = 0; i < response->hdr_count; i++) { + grpc_http_header *header = &response->hdrs[i]; + if (strcmp(header->key, "Metadata-Flavor") == 0 && + strcmp(header->value, "Google") == 0) { + detector->success = 1; + break; + } + } + } + gpr_mu_lock(g_polling_mu); + detector->is_done = 1; + grpc_pollset_kick(detector->pollset, NULL); + gpr_mu_unlock(g_polling_mu); +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool s) { + grpc_pollset_destroy(p); +} + +static int is_stack_running_on_compute_engine(void) { + compute_engine_detector detector; + grpc_httpcli_request request; + grpc_httpcli_context context; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_closure destroy_closure; + + /* The http call is local. If it takes more than one sec, it is for sure not + on compute engine. */ + gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN); + + detector.pollset = gpr_malloc(grpc_pollset_size()); + grpc_pollset_init(detector.pollset, &g_polling_mu); + detector.is_done = 0; + detector.success = 0; + + memset(&request, 0, sizeof(grpc_httpcli_request)); + request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST; + request.http.path = "/"; + + grpc_httpcli_context_init(&context); + + grpc_httpcli_get( + &exec_ctx, &context, detector.pollset, &request, + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay), + on_compute_engine_detection_http_response, &detector); + + grpc_exec_ctx_finish(&exec_ctx); + + /* Block until we get the response. This is not ideal but this should only be + called once for the lifetime of the process by the default credentials. */ + gpr_mu_lock(g_polling_mu); + while (!detector.is_done) { + grpc_pollset_worker *worker = NULL; + grpc_pollset_work(&exec_ctx, detector.pollset, &worker, + gpr_now(GPR_CLOCK_MONOTONIC), + gpr_inf_future(GPR_CLOCK_MONOTONIC)); + } + gpr_mu_unlock(g_polling_mu); + + grpc_httpcli_context_destroy(&context); + grpc_closure_init(&destroy_closure, destroy_pollset, detector.pollset); + grpc_pollset_shutdown(&exec_ctx, detector.pollset, &destroy_closure); + grpc_exec_ctx_finish(&exec_ctx); + g_polling_mu = NULL; + + gpr_free(detector.pollset); + + return detector.success; +} + +/* Takes ownership of creds_path if not NULL. */ +static grpc_call_credentials *create_default_creds_from_path(char *creds_path) { + grpc_json *json = NULL; + grpc_auth_json_key key; + grpc_auth_refresh_token token; + grpc_call_credentials *result = NULL; + gpr_slice creds_data = gpr_empty_slice(); + int file_ok = 0; + if (creds_path == NULL) goto end; + creds_data = gpr_load_file(creds_path, 0, &file_ok); + if (!file_ok) goto end; + json = grpc_json_parse_string_with_len( + (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data)); + if (json == NULL) goto end; + + /* First, try an auth json key. */ + key = grpc_auth_json_key_create_from_json(json); + if (grpc_auth_json_key_is_valid(&key)) { + result = + grpc_service_account_jwt_access_credentials_create_from_auth_json_key( + key, grpc_max_auth_token_lifetime()); + goto end; + } + + /* Then try a refresh token if the auth json key was invalid. */ + token = grpc_auth_refresh_token_create_from_json(json); + if (grpc_auth_refresh_token_is_valid(&token)) { + result = + grpc_refresh_token_credentials_create_from_auth_refresh_token(token); + goto end; + } + +end: + if (creds_path != NULL) gpr_free(creds_path); + gpr_slice_unref(creds_data); + if (json != NULL) grpc_json_destroy(json); + return result; +} + +grpc_channel_credentials *grpc_google_default_credentials_create(void) { + grpc_channel_credentials *result = NULL; + grpc_call_credentials *call_creds = NULL; + + GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ()); + + gpr_once_init(&g_once, init_default_credentials); + + gpr_mu_lock(&g_state_mu); + + if (default_credentials != NULL) { + result = grpc_channel_credentials_ref(default_credentials); + goto end; + } + + /* First, try the environment variable. */ + call_creds = create_default_creds_from_path( + gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR)); + if (call_creds != NULL) goto end; + + /* Then the well-known file. */ + call_creds = create_default_creds_from_path( + grpc_get_well_known_google_credentials_file_path()); + if (call_creds != NULL) goto end; + + /* At last try to see if we're on compute engine (do the detection only once + since it requires a network test). */ + if (!compute_engine_detection_done) { + int need_compute_engine_creds = is_stack_running_on_compute_engine(); + compute_engine_detection_done = 1; + if (need_compute_engine_creds) { + call_creds = grpc_google_compute_engine_credentials_create(NULL); + } + } + +end: + if (result == NULL) { + if (call_creds != NULL) { + /* Blend with default ssl credentials and add a global reference so that + it + can be cached and re-served. */ + grpc_channel_credentials *ssl_creds = + grpc_ssl_credentials_create(NULL, NULL, NULL); + default_credentials = grpc_channel_credentials_ref( + grpc_composite_channel_credentials_create(ssl_creds, call_creds, + NULL)); + GPR_ASSERT(default_credentials != NULL); + grpc_channel_credentials_unref(ssl_creds); + grpc_call_credentials_unref(call_creds); + result = default_credentials; + } else { + gpr_log(GPR_ERROR, "Could not create google default credentials."); + } + } + gpr_mu_unlock(&g_state_mu); + return result; +} + +void grpc_flush_cached_google_default_credentials(void) { + gpr_once_init(&g_once, init_default_credentials); + gpr_mu_lock(&g_state_mu); + if (default_credentials != NULL) { + grpc_channel_credentials_unref(default_credentials); + default_credentials = NULL; + } + compute_engine_detection_done = 0; + gpr_mu_unlock(&g_state_mu); +} + +/* -- Well known credentials path. -- */ + +static grpc_well_known_credentials_path_getter creds_path_getter = NULL; + +char *grpc_get_well_known_google_credentials_file_path(void) { + if (creds_path_getter != NULL) return creds_path_getter(); + return grpc_get_well_known_google_credentials_file_path_impl(); +} + +void grpc_override_well_known_credentials_path_getter( + grpc_well_known_credentials_path_getter getter) { + creds_path_getter = getter; +} diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.h b/src/core/lib/security/credentials/google_default/google_default_credentials.h new file mode 100644 index 0000000000..33e8c2ec8d --- /dev/null +++ b/src/core/lib/security/credentials/google_default/google_default_credentials.h @@ -0,0 +1,47 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_CREDENTIALS_H + +#include "src/core/lib/security/credentials/credentials.h" + +#define GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY "gcloud" +#define GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE \ + "application_default_credentials.json" + +void grpc_flush_cached_google_default_credentials(void); + +#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_CREDENTIALS_H + + diff --git a/src/core/lib/security/credentials/iam/iam_credentials.c b/src/core/lib/security/credentials/iam/iam_credentials.c new file mode 100644 index 0000000000..ec0f2841f2 --- /dev/null +++ b/src/core/lib/security/credentials/iam/iam_credentials.c @@ -0,0 +1,87 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/iam/iam_credentials.h" + +#include + +#include "src/core/lib/surface/api_trace.h" + +#include +#include +#include +#include + +static void iam_destruct(grpc_call_credentials *creds) { + grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; + grpc_credentials_md_store_unref(c->iam_md); +} + +static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + grpc_auth_metadata_context context, + grpc_credentials_metadata_cb cb, + void *user_data) { + grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; + cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries, + GRPC_CREDENTIALS_OK); +} + +static grpc_call_credentials_vtable iam_vtable = {iam_destruct, + iam_get_request_metadata}; + +grpc_call_credentials *grpc_google_iam_credentials_create( + const char *token, const char *authority_selector, void *reserved) { + grpc_google_iam_credentials *c; + GRPC_API_TRACE( + "grpc_iam_credentials_create(token=%s, authority_selector=%s, " + "reserved=%p)", + 3, (token, authority_selector, reserved)); + GPR_ASSERT(reserved == NULL); + GPR_ASSERT(token != NULL); + GPR_ASSERT(authority_selector != NULL); + c = gpr_malloc(sizeof(grpc_google_iam_credentials)); + memset(c, 0, sizeof(grpc_google_iam_credentials)); + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM; + c->base.vtable = &iam_vtable; + gpr_ref_init(&c->base.refcount, 1); + c->iam_md = grpc_credentials_md_store_create(2); + grpc_credentials_md_store_add_cstrings( + c->iam_md, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, token); + grpc_credentials_md_store_add_cstrings( + c->iam_md, GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, authority_selector); + return &c->base; +} + + diff --git a/src/core/lib/security/credentials/iam/iam_credentials.h b/src/core/lib/security/credentials/iam/iam_credentials.h new file mode 100644 index 0000000000..7110eaf478 --- /dev/null +++ b/src/core/lib/security/credentials/iam/iam_credentials.h @@ -0,0 +1,47 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_CREDENTIALS_H + +#include "src/core/lib/security/credentials/credentials.h" + +typedef struct { + grpc_call_credentials base; + grpc_credentials_md_store *iam_md; +} grpc_google_iam_credentials; + +#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_IAM_CREDENTIALS_H + + + diff --git a/src/core/lib/security/credentials/jwt/json_token.c b/src/core/lib/security/credentials/jwt/json_token.c new file mode 100644 index 0000000000..fd3d0d6a64 --- /dev/null +++ b/src/core/lib/security/credentials/jwt/json_token.c @@ -0,0 +1,321 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/jwt/json_token.h" + +#include + +#include +#include +#include + +#include "src/core/lib/security/util/b64.h" +#include "src/core/lib/security/util/json_util.h" +#include "src/core/lib/support/string.h" + +#include +#include +#include + +/* --- Constants. --- */ + +/* 1 hour max. */ +gpr_timespec grpc_max_auth_token_lifetime() { + gpr_timespec out; + out.tv_sec = 3600; + out.tv_nsec = 0; + out.clock_type = GPR_TIMESPAN; + return out; +} + +#define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256" +#define GRPC_JWT_TYPE "JWT" + +/* --- Override for testing. --- */ + +static grpc_jwt_encode_and_sign_override g_jwt_encode_and_sign_override = NULL; + +/* --- grpc_auth_json_key. --- */ + +int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key) { + return (json_key != NULL) && + strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID); +} + +grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json) { + grpc_auth_json_key result; + BIO *bio = NULL; + const char *prop_value; + int success = 0; + + memset(&result, 0, sizeof(grpc_auth_json_key)); + result.type = GRPC_AUTH_JSON_TYPE_INVALID; + if (json == NULL) { + gpr_log(GPR_ERROR, "Invalid json."); + goto end; + } + + prop_value = grpc_json_get_string_property(json, "type"); + if (prop_value == NULL || + strcmp(prop_value, GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT)) { + goto end; + } + result.type = GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT; + + if (!grpc_copy_json_string_property(json, "private_key_id", + &result.private_key_id) || + !grpc_copy_json_string_property(json, "client_id", &result.client_id) || + !grpc_copy_json_string_property(json, "client_email", + &result.client_email)) { + goto end; + } + + prop_value = grpc_json_get_string_property(json, "private_key"); + if (prop_value == NULL) { + goto end; + } + bio = BIO_new(BIO_s_mem()); + success = BIO_puts(bio, prop_value); + if ((success < 0) || ((size_t)success != strlen(prop_value))) { + gpr_log(GPR_ERROR, "Could not write into openssl BIO."); + goto end; + } + result.private_key = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, ""); + if (result.private_key == NULL) { + gpr_log(GPR_ERROR, "Could not deserialize private key."); + goto end; + } + success = 1; + +end: + if (bio != NULL) BIO_free(bio); + if (!success) grpc_auth_json_key_destruct(&result); + return result; +} + +grpc_auth_json_key grpc_auth_json_key_create_from_string( + const char *json_string) { + char *scratchpad = gpr_strdup(json_string); + grpc_json *json = grpc_json_parse_string(scratchpad); + grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json); + if (json != NULL) grpc_json_destroy(json); + gpr_free(scratchpad); + return result; +} + +void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key) { + if (json_key == NULL) return; + json_key->type = GRPC_AUTH_JSON_TYPE_INVALID; + if (json_key->client_id != NULL) { + gpr_free(json_key->client_id); + json_key->client_id = NULL; + } + if (json_key->private_key_id != NULL) { + gpr_free(json_key->private_key_id); + json_key->private_key_id = NULL; + } + if (json_key->client_email != NULL) { + gpr_free(json_key->client_email); + json_key->client_email = NULL; + } + if (json_key->private_key != NULL) { + RSA_free(json_key->private_key); + json_key->private_key = NULL; + } +} + +/* --- jwt encoding and signature. --- */ + +static grpc_json *create_child(grpc_json *brother, grpc_json *parent, + const char *key, const char *value, + grpc_json_type type) { + grpc_json *child = grpc_json_create(type); + if (brother) brother->next = child; + if (!parent->child) parent->child = child; + child->parent = parent; + child->value = value; + child->key = key; + return child; +} + +static char *encoded_jwt_header(const char *key_id, const char *algorithm) { + grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json *child = NULL; + char *json_str = NULL; + char *result = NULL; + + child = create_child(NULL, json, "alg", algorithm, GRPC_JSON_STRING); + child = create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING); + create_child(child, json, "kid", key_id, GRPC_JSON_STRING); + + json_str = grpc_json_dump_to_string(json, 0); + result = grpc_base64_encode(json_str, strlen(json_str), 1, 0); + gpr_free(json_str); + grpc_json_destroy(json); + return result; +} + +static char *encoded_jwt_claim(const grpc_auth_json_key *json_key, + const char *audience, + gpr_timespec token_lifetime, const char *scope) { + grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json *child = NULL; + char *json_str = NULL; + char *result = NULL; + gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); + gpr_timespec expiration = gpr_time_add(now, token_lifetime); + char now_str[GPR_LTOA_MIN_BUFSIZE]; + char expiration_str[GPR_LTOA_MIN_BUFSIZE]; + if (gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime()) > 0) { + gpr_log(GPR_INFO, "Cropping token lifetime to maximum allowed value."); + expiration = gpr_time_add(now, grpc_max_auth_token_lifetime()); + } + int64_ttoa(now.tv_sec, now_str); + int64_ttoa(expiration.tv_sec, expiration_str); + + child = + create_child(NULL, json, "iss", json_key->client_email, GRPC_JSON_STRING); + if (scope != NULL) { + child = create_child(child, json, "scope", scope, GRPC_JSON_STRING); + } else { + /* Unscoped JWTs need a sub field. */ + child = create_child(child, json, "sub", json_key->client_email, + GRPC_JSON_STRING); + } + + child = create_child(child, json, "aud", audience, GRPC_JSON_STRING); + child = create_child(child, json, "iat", now_str, GRPC_JSON_NUMBER); + create_child(child, json, "exp", expiration_str, GRPC_JSON_NUMBER); + + json_str = grpc_json_dump_to_string(json, 0); + result = grpc_base64_encode(json_str, strlen(json_str), 1, 0); + gpr_free(json_str); + grpc_json_destroy(json); + return result; +} + +static char *dot_concat_and_free_strings(char *str1, char *str2) { + size_t str1_len = strlen(str1); + size_t str2_len = strlen(str2); + size_t result_len = str1_len + 1 /* dot */ + str2_len; + char *result = gpr_malloc(result_len + 1 /* NULL terminated */); + char *current = result; + memcpy(current, str1, str1_len); + current += str1_len; + *(current++) = '.'; + memcpy(current, str2, str2_len); + current += str2_len; + GPR_ASSERT(current >= result); + GPR_ASSERT((uintptr_t)(current - result) == result_len); + *current = '\0'; + gpr_free(str1); + gpr_free(str2); + return result; +} + +const EVP_MD *openssl_digest_from_algorithm(const char *algorithm) { + if (strcmp(algorithm, GRPC_JWT_RSA_SHA256_ALGORITHM) == 0) { + return EVP_sha256(); + } else { + gpr_log(GPR_ERROR, "Unknown algorithm %s.", algorithm); + return NULL; + } +} + +char *compute_and_encode_signature(const grpc_auth_json_key *json_key, + const char *signature_algorithm, + const char *to_sign) { + const EVP_MD *md = openssl_digest_from_algorithm(signature_algorithm); + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY *key = EVP_PKEY_new(); + size_t sig_len = 0; + unsigned char *sig = NULL; + char *result = NULL; + if (md == NULL) return NULL; + md_ctx = EVP_MD_CTX_create(); + if (md_ctx == NULL) { + gpr_log(GPR_ERROR, "Could not create MD_CTX"); + goto end; + } + EVP_PKEY_set1_RSA(key, json_key->private_key); + if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, key) != 1) { + gpr_log(GPR_ERROR, "DigestInit failed."); + goto end; + } + if (EVP_DigestSignUpdate(md_ctx, to_sign, strlen(to_sign)) != 1) { + gpr_log(GPR_ERROR, "DigestUpdate failed."); + goto end; + } + if (EVP_DigestSignFinal(md_ctx, NULL, &sig_len) != 1) { + gpr_log(GPR_ERROR, "DigestFinal (get signature length) failed."); + goto end; + } + sig = gpr_malloc(sig_len); + if (EVP_DigestSignFinal(md_ctx, sig, &sig_len) != 1) { + gpr_log(GPR_ERROR, "DigestFinal (signature compute) failed."); + goto end; + } + result = grpc_base64_encode(sig, sig_len, 1, 0); + +end: + if (key != NULL) EVP_PKEY_free(key); + if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); + if (sig != NULL) gpr_free(sig); + return result; +} + +char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key, + const char *audience, + gpr_timespec token_lifetime, const char *scope) { + if (g_jwt_encode_and_sign_override != NULL) { + return g_jwt_encode_and_sign_override(json_key, audience, token_lifetime, + scope); + } else { + const char *sig_algo = GRPC_JWT_RSA_SHA256_ALGORITHM; + char *to_sign = dot_concat_and_free_strings( + encoded_jwt_header(json_key->private_key_id, sig_algo), + encoded_jwt_claim(json_key, audience, token_lifetime, scope)); + char *sig = compute_and_encode_signature(json_key, sig_algo, to_sign); + if (sig == NULL) { + gpr_free(to_sign); + return NULL; + } + return dot_concat_and_free_strings(to_sign, sig); + } +} + +void grpc_jwt_encode_and_sign_set_override( + grpc_jwt_encode_and_sign_override func) { + g_jwt_encode_and_sign_override = func; +} + diff --git a/src/core/lib/security/credentials/jwt/json_token.h b/src/core/lib/security/credentials/jwt/json_token.h new file mode 100644 index 0000000000..07fc5bf0e0 --- /dev/null +++ b/src/core/lib/security/credentials/jwt/json_token.h @@ -0,0 +1,88 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JSON_TOKEN_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JSON_TOKEN_H + +#include +#include + +#include "src/core/lib/json/json.h" + +/* --- Constants. --- */ + +#define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token" + +/* --- auth_json_key parsing. --- */ + +typedef struct { + const char *type; + char *private_key_id; + char *client_id; + char *client_email; + RSA *private_key; +} grpc_auth_json_key; + +/* Returns 1 if the object is valid, 0 otherwise. */ +int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key); + +/* Creates a json_key object from string. Returns an invalid object if a parsing + error has been encountered. */ +grpc_auth_json_key grpc_auth_json_key_create_from_string( + const char *json_string); + +/* Creates a json_key object from parsed json. Returns an invalid object if a + parsing error has been encountered. */ +grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json); + +/* Destructs the object. */ +void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key); + +/* --- json token encoding and signing. --- */ + +/* Caller is responsible for calling gpr_free on the returned value. May return + NULL on invalid input. The scope parameter may be NULL. */ +char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key, + const char *audience, + gpr_timespec token_lifetime, const char *scope); + +/* Override encode_and_sign function for testing. */ +typedef char *(*grpc_jwt_encode_and_sign_override)( + const grpc_auth_json_key *json_key, const char *audience, + gpr_timespec token_lifetime, const char *scope); + +/* Set a custom encode_and_sign override for testing. */ +void grpc_jwt_encode_and_sign_set_override( + grpc_jwt_encode_and_sign_override func); + +#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JSON_TOKEN_H */ diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.c b/src/core/lib/security/credentials/jwt/jwt_credentials.c new file mode 100644 index 0000000000..9fd0527a52 --- /dev/null +++ b/src/core/lib/security/credentials/jwt/jwt_credentials.c @@ -0,0 +1,161 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/jwt/jwt_credentials.h" + +#include + +#include "src/core/lib/surface/api_trace.h" + +#include +#include +#include +#include + +static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) { + if (c->cached.jwt_md != NULL) { + grpc_credentials_md_store_unref(c->cached.jwt_md); + c->cached.jwt_md = NULL; + } + if (c->cached.service_url != NULL) { + gpr_free(c->cached.service_url); + c->cached.service_url = NULL; + } + c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); +} + +static void jwt_destruct(grpc_call_credentials *creds) { + grpc_service_account_jwt_access_credentials *c = + (grpc_service_account_jwt_access_credentials *)creds; + grpc_auth_json_key_destruct(&c->key); + jwt_reset_cache(c); + gpr_mu_destroy(&c->cache_mu); +} + +static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + grpc_auth_metadata_context context, + grpc_credentials_metadata_cb cb, + void *user_data) { + grpc_service_account_jwt_access_credentials *c = + (grpc_service_account_jwt_access_credentials *)creds; + gpr_timespec refresh_threshold = gpr_time_from_seconds( + GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN); + + /* See if we can return a cached jwt. */ + grpc_credentials_md_store *jwt_md = NULL; + { + gpr_mu_lock(&c->cache_mu); + if (c->cached.service_url != NULL && + strcmp(c->cached.service_url, context.service_url) == 0 && + c->cached.jwt_md != NULL && + (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, + gpr_now(GPR_CLOCK_REALTIME)), + refresh_threshold) > 0)) { + jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md); + } + gpr_mu_unlock(&c->cache_mu); + } + + if (jwt_md == NULL) { + char *jwt = NULL; + /* Generate a new jwt. */ + gpr_mu_lock(&c->cache_mu); + jwt_reset_cache(c); + jwt = grpc_jwt_encode_and_sign(&c->key, context.service_url, + c->jwt_lifetime, NULL); + if (jwt != NULL) { + char *md_value; + gpr_asprintf(&md_value, "Bearer %s", jwt); + gpr_free(jwt); + c->cached.jwt_expiration = + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime); + c->cached.service_url = gpr_strdup(context.service_url); + c->cached.jwt_md = grpc_credentials_md_store_create(1); + grpc_credentials_md_store_add_cstrings( + c->cached.jwt_md, GRPC_AUTHORIZATION_METADATA_KEY, md_value); + gpr_free(md_value); + jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md); + } + gpr_mu_unlock(&c->cache_mu); + } + + if (jwt_md != NULL) { + cb(exec_ctx, user_data, jwt_md->entries, jwt_md->num_entries, + GRPC_CREDENTIALS_OK); + grpc_credentials_md_store_unref(jwt_md); + } else { + cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); + } +} + +static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct, + jwt_get_request_metadata}; + +grpc_call_credentials * +grpc_service_account_jwt_access_credentials_create_from_auth_json_key( + grpc_auth_json_key key, gpr_timespec token_lifetime) { + grpc_service_account_jwt_access_credentials *c; + if (!grpc_auth_json_key_is_valid(&key)) { + gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation"); + return NULL; + } + c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials)); + memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials)); + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT; + gpr_ref_init(&c->base.refcount, 1); + c->base.vtable = &jwt_vtable; + c->key = key; + c->jwt_lifetime = token_lifetime; + gpr_mu_init(&c->cache_mu); + jwt_reset_cache(c); + return &c->base; +} + +grpc_call_credentials *grpc_service_account_jwt_access_credentials_create( + const char *json_key, gpr_timespec token_lifetime, void *reserved) { + GRPC_API_TRACE( + "grpc_service_account_jwt_access_credentials_create(" + "json_key=%s, " + "token_lifetime=" + "gpr_timespec { tv_sec: %lld, tv_nsec: %d, clock_type: %d }, " + "reserved=%p)", + 5, + (json_key, (long long)token_lifetime.tv_sec, (int)token_lifetime.tv_nsec, + (int)token_lifetime.clock_type, reserved)); + GPR_ASSERT(reserved == NULL); + return grpc_service_account_jwt_access_credentials_create_from_auth_json_key( + grpc_auth_json_key_create_from_string(json_key), token_lifetime); +} + diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.h b/src/core/lib/security/credentials/jwt/jwt_credentials.h new file mode 100644 index 0000000000..6faf676414 --- /dev/null +++ b/src/core/lib/security/credentials/jwt/jwt_credentials.h @@ -0,0 +1,63 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_CREDENTIALS_H + +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/credentials/jwt/json_token.h" + +typedef struct { + grpc_call_credentials base; + + // Have a simple cache for now with just 1 entry. We could have a map based on + // the service_url for a more sophisticated one. + gpr_mu cache_mu; + struct { + grpc_credentials_md_store *jwt_md; + char *service_url; + gpr_timespec jwt_expiration; + } cached; + + grpc_auth_json_key key; + gpr_timespec jwt_lifetime; +} grpc_service_account_jwt_access_credentials; + +// Private constructor for jwt credentials from an already parsed json key. +// Takes ownership of the key. +grpc_call_credentials * +grpc_service_account_jwt_access_credentials_create_from_auth_json_key( + grpc_auth_json_key key, gpr_timespec token_lifetime); + +#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_CREDENTIALS_H + diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c new file mode 100644 index 0000000000..cd6c7ce392 --- /dev/null +++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c @@ -0,0 +1,843 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/jwt/jwt_verifier.h" + +#include +#include + +#include "src/core/lib/http/httpcli.h" +#include "src/core/lib/security/util/b64.h" +#include "src/core/lib/tsi/ssl_types.h" + +#include +#include +#include +#include +#include + +/* --- Utils. --- */ + +const char *grpc_jwt_verifier_status_to_string( + grpc_jwt_verifier_status status) { + switch (status) { + case GRPC_JWT_VERIFIER_OK: + return "OK"; + case GRPC_JWT_VERIFIER_BAD_SIGNATURE: + return "BAD_SIGNATURE"; + case GRPC_JWT_VERIFIER_BAD_FORMAT: + return "BAD_FORMAT"; + case GRPC_JWT_VERIFIER_BAD_AUDIENCE: + return "BAD_AUDIENCE"; + case GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR: + return "KEY_RETRIEVAL_ERROR"; + case GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE: + return "TIME_CONSTRAINT_FAILURE"; + case GRPC_JWT_VERIFIER_GENERIC_ERROR: + return "GENERIC_ERROR"; + default: + return "UNKNOWN"; + } +} + +static const EVP_MD *evp_md_from_alg(const char *alg) { + if (strcmp(alg, "RS256") == 0) { + return EVP_sha256(); + } else if (strcmp(alg, "RS384") == 0) { + return EVP_sha384(); + } else if (strcmp(alg, "RS512") == 0) { + return EVP_sha512(); + } else { + return NULL; + } +} + +static grpc_json *parse_json_part_from_jwt(const char *str, size_t len, + gpr_slice *buffer) { + grpc_json *json; + + *buffer = grpc_base64_decode_with_len(str, len, 1); + if (GPR_SLICE_IS_EMPTY(*buffer)) { + gpr_log(GPR_ERROR, "Invalid base64."); + return NULL; + } + json = grpc_json_parse_string_with_len((char *)GPR_SLICE_START_PTR(*buffer), + GPR_SLICE_LENGTH(*buffer)); + if (json == NULL) { + gpr_slice_unref(*buffer); + gpr_log(GPR_ERROR, "JSON parsing error."); + } + return json; +} + +static const char *validate_string_field(const grpc_json *json, + const char *key) { + if (json->type != GRPC_JSON_STRING) { + gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value); + return NULL; + } + return json->value; +} + +static gpr_timespec validate_time_field(const grpc_json *json, + const char *key) { + gpr_timespec result = gpr_time_0(GPR_CLOCK_REALTIME); + if (json->type != GRPC_JSON_NUMBER) { + gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value); + return result; + } + result.tv_sec = strtol(json->value, NULL, 10); + return result; +} + +/* --- JOSE header. see http://tools.ietf.org/html/rfc7515#section-4 --- */ + +typedef struct { + const char *alg; + const char *kid; + const char *typ; + /* TODO(jboeuf): Add others as needed (jku, jwk, x5u, x5c and so on...). */ + gpr_slice buffer; +} jose_header; + +static void jose_header_destroy(jose_header *h) { + gpr_slice_unref(h->buffer); + gpr_free(h); +} + +/* Takes ownership of json and buffer. */ +static jose_header *jose_header_from_json(grpc_json *json, gpr_slice buffer) { + grpc_json *cur; + jose_header *h = gpr_malloc(sizeof(jose_header)); + memset(h, 0, sizeof(jose_header)); + h->buffer = buffer; + for (cur = json->child; cur != NULL; cur = cur->next) { + if (strcmp(cur->key, "alg") == 0) { + /* We only support RSA-1.5 signatures for now. + Beware of this if we add HMAC support: + https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ + */ + if (cur->type != GRPC_JSON_STRING || strncmp(cur->value, "RS", 2) || + evp_md_from_alg(cur->value) == NULL) { + gpr_log(GPR_ERROR, "Invalid alg field [%s]", cur->value); + goto error; + } + h->alg = cur->value; + } else if (strcmp(cur->key, "typ") == 0) { + h->typ = validate_string_field(cur, "typ"); + if (h->typ == NULL) goto error; + } else if (strcmp(cur->key, "kid") == 0) { + h->kid = validate_string_field(cur, "kid"); + if (h->kid == NULL) goto error; + } + } + if (h->alg == NULL) { + gpr_log(GPR_ERROR, "Missing alg field."); + goto error; + } + grpc_json_destroy(json); + h->buffer = buffer; + return h; + +error: + grpc_json_destroy(json); + jose_header_destroy(h); + return NULL; +} + +/* --- JWT claims. see http://tools.ietf.org/html/rfc7519#section-4.1 */ + +struct grpc_jwt_claims { + /* Well known properties already parsed. */ + const char *sub; + const char *iss; + const char *aud; + const char *jti; + gpr_timespec iat; + gpr_timespec exp; + gpr_timespec nbf; + + grpc_json *json; + gpr_slice buffer; +}; + +void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) { + grpc_json_destroy(claims->json); + gpr_slice_unref(claims->buffer); + gpr_free(claims); +} + +const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims) { + if (claims == NULL) return NULL; + return claims->json; +} + +const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims) { + if (claims == NULL) return NULL; + return claims->sub; +} + +const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims) { + if (claims == NULL) return NULL; + return claims->iss; +} + +const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims) { + if (claims == NULL) return NULL; + return claims->jti; +} + +const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims) { + if (claims == NULL) return NULL; + return claims->aud; +} + +gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims) { + if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME); + return claims->iat; +} + +gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims) { + if (claims == NULL) return gpr_inf_future(GPR_CLOCK_REALTIME); + return claims->exp; +} + +gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims) { + if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME); + return claims->nbf; +} + +/* Takes ownership of json and buffer even in case of failure. */ +grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer) { + grpc_json *cur; + grpc_jwt_claims *claims = gpr_malloc(sizeof(grpc_jwt_claims)); + memset(claims, 0, sizeof(grpc_jwt_claims)); + claims->json = json; + claims->buffer = buffer; + claims->iat = gpr_inf_past(GPR_CLOCK_REALTIME); + claims->nbf = gpr_inf_past(GPR_CLOCK_REALTIME); + claims->exp = gpr_inf_future(GPR_CLOCK_REALTIME); + + /* Per the spec, all fields are optional. */ + for (cur = json->child; cur != NULL; cur = cur->next) { + if (strcmp(cur->key, "sub") == 0) { + claims->sub = validate_string_field(cur, "sub"); + if (claims->sub == NULL) goto error; + } else if (strcmp(cur->key, "iss") == 0) { + claims->iss = validate_string_field(cur, "iss"); + if (claims->iss == NULL) goto error; + } else if (strcmp(cur->key, "aud") == 0) { + claims->aud = validate_string_field(cur, "aud"); + if (claims->aud == NULL) goto error; + } else if (strcmp(cur->key, "jti") == 0) { + claims->jti = validate_string_field(cur, "jti"); + if (claims->jti == NULL) goto error; + } else if (strcmp(cur->key, "iat") == 0) { + claims->iat = validate_time_field(cur, "iat"); + if (gpr_time_cmp(claims->iat, gpr_time_0(GPR_CLOCK_REALTIME)) == 0) + goto error; + } else if (strcmp(cur->key, "exp") == 0) { + claims->exp = validate_time_field(cur, "exp"); + if (gpr_time_cmp(claims->exp, gpr_time_0(GPR_CLOCK_REALTIME)) == 0) + goto error; + } else if (strcmp(cur->key, "nbf") == 0) { + claims->nbf = validate_time_field(cur, "nbf"); + if (gpr_time_cmp(claims->nbf, gpr_time_0(GPR_CLOCK_REALTIME)) == 0) + goto error; + } + } + return claims; + +error: + grpc_jwt_claims_destroy(claims); + return NULL; +} + +grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims, + const char *audience) { + gpr_timespec skewed_now; + int audience_ok; + + GPR_ASSERT(claims != NULL); + + skewed_now = + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew); + if (gpr_time_cmp(skewed_now, claims->nbf) < 0) { + gpr_log(GPR_ERROR, "JWT is not valid yet."); + return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE; + } + skewed_now = + gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew); + if (gpr_time_cmp(skewed_now, claims->exp) > 0) { + gpr_log(GPR_ERROR, "JWT is expired."); + return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE; + } + + if (audience == NULL) { + audience_ok = claims->aud == NULL; + } else { + audience_ok = claims->aud != NULL && strcmp(audience, claims->aud) == 0; + } + if (!audience_ok) { + gpr_log(GPR_ERROR, "Audience mismatch: expected %s and found %s.", + audience == NULL ? "NULL" : audience, + claims->aud == NULL ? "NULL" : claims->aud); + return GRPC_JWT_VERIFIER_BAD_AUDIENCE; + } + return GRPC_JWT_VERIFIER_OK; +} + +/* --- verifier_cb_ctx object. --- */ + +typedef struct { + grpc_jwt_verifier *verifier; + grpc_pollset *pollset; + jose_header *header; + grpc_jwt_claims *claims; + char *audience; + gpr_slice signature; + gpr_slice signed_data; + void *user_data; + grpc_jwt_verification_done_cb user_cb; +} verifier_cb_ctx; + +/* Takes ownership of the header, claims and signature. */ +static verifier_cb_ctx *verifier_cb_ctx_create( + grpc_jwt_verifier *verifier, grpc_pollset *pollset, jose_header *header, + grpc_jwt_claims *claims, const char *audience, gpr_slice signature, + const char *signed_jwt, size_t signed_jwt_len, void *user_data, + grpc_jwt_verification_done_cb cb) { + verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx)); + memset(ctx, 0, sizeof(verifier_cb_ctx)); + ctx->verifier = verifier; + ctx->pollset = pollset; + ctx->header = header; + ctx->audience = gpr_strdup(audience); + ctx->claims = claims; + ctx->signature = signature; + ctx->signed_data = gpr_slice_from_copied_buffer(signed_jwt, signed_jwt_len); + ctx->user_data = user_data; + ctx->user_cb = cb; + return ctx; +} + +void verifier_cb_ctx_destroy(verifier_cb_ctx *ctx) { + if (ctx->audience != NULL) gpr_free(ctx->audience); + if (ctx->claims != NULL) grpc_jwt_claims_destroy(ctx->claims); + gpr_slice_unref(ctx->signature); + gpr_slice_unref(ctx->signed_data); + jose_header_destroy(ctx->header); + /* TODO: see what to do with claims... */ + gpr_free(ctx); +} + +/* --- grpc_jwt_verifier object. --- */ + +/* Clock skew defaults to one minute. */ +gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0, GPR_TIMESPAN}; + +/* Max delay defaults to one minute. */ +gpr_timespec grpc_jwt_verifier_max_delay = {60, 0, GPR_TIMESPAN}; + +typedef struct { + char *email_domain; + char *key_url_prefix; +} email_key_mapping; + +struct grpc_jwt_verifier { + email_key_mapping *mappings; + size_t num_mappings; /* Should be very few, linear search ok. */ + size_t allocated_mappings; + grpc_httpcli_context http_ctx; +}; + +static grpc_json *json_from_http(const grpc_httpcli_response *response) { + grpc_json *json = NULL; + + if (response == NULL) { + gpr_log(GPR_ERROR, "HTTP response is NULL."); + return NULL; + } + if (response->status != 200) { + gpr_log(GPR_ERROR, "Call to http server failed with error %d.", + response->status); + return NULL; + } + + json = grpc_json_parse_string_with_len(response->body, response->body_length); + if (json == NULL) { + gpr_log(GPR_ERROR, "Invalid JSON found in response."); + } + return json; +} + +static const grpc_json *find_property_by_name(const grpc_json *json, + const char *name) { + const grpc_json *cur; + for (cur = json->child; cur != NULL; cur = cur->next) { + if (strcmp(cur->key, name) == 0) return cur; + } + return NULL; +} + +static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) { + X509 *x509 = NULL; + EVP_PKEY *result = NULL; + BIO *bio = BIO_new(BIO_s_mem()); + size_t len = strlen(x509_str); + GPR_ASSERT(len < INT_MAX); + BIO_write(bio, x509_str, (int)len); + x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (x509 == NULL) { + gpr_log(GPR_ERROR, "Unable to parse x509 cert."); + goto end; + } + result = X509_get_pubkey(x509); + if (result == NULL) { + gpr_log(GPR_ERROR, "Cannot find public key in X509 cert."); + } + +end: + BIO_free(bio); + if (x509 != NULL) X509_free(x509); + return result; +} + +static BIGNUM *bignum_from_base64(const char *b64) { + BIGNUM *result = NULL; + gpr_slice bin; + + if (b64 == NULL) return NULL; + bin = grpc_base64_decode(b64, 1); + if (GPR_SLICE_IS_EMPTY(bin)) { + gpr_log(GPR_ERROR, "Invalid base64 for big num."); + return NULL; + } + result = BN_bin2bn(GPR_SLICE_START_PTR(bin), + TSI_SIZE_AS_SIZE(GPR_SLICE_LENGTH(bin)), NULL); + gpr_slice_unref(bin); + return result; +} + +static EVP_PKEY *pkey_from_jwk(const grpc_json *json, const char *kty) { + const grpc_json *key_prop; + RSA *rsa = NULL; + EVP_PKEY *result = NULL; + + GPR_ASSERT(kty != NULL && json != NULL); + if (strcmp(kty, "RSA") != 0) { + gpr_log(GPR_ERROR, "Unsupported key type %s.", kty); + goto end; + } + rsa = RSA_new(); + if (rsa == NULL) { + gpr_log(GPR_ERROR, "Could not create rsa key."); + goto end; + } + for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) { + if (strcmp(key_prop->key, "n") == 0) { + rsa->n = bignum_from_base64(validate_string_field(key_prop, "n")); + if (rsa->n == NULL) goto end; + } else if (strcmp(key_prop->key, "e") == 0) { + rsa->e = bignum_from_base64(validate_string_field(key_prop, "e")); + if (rsa->e == NULL) goto end; + } + } + if (rsa->e == NULL || rsa->n == NULL) { + gpr_log(GPR_ERROR, "Missing RSA public key field."); + goto end; + } + result = EVP_PKEY_new(); + EVP_PKEY_set1_RSA(result, rsa); /* uprefs rsa. */ + +end: + if (rsa != NULL) RSA_free(rsa); + return result; +} + +static EVP_PKEY *find_verification_key(const grpc_json *json, + const char *header_alg, + const char *header_kid) { + const grpc_json *jkey; + const grpc_json *jwk_keys; + /* Try to parse the json as a JWK set: + https://tools.ietf.org/html/rfc7517#section-5. */ + jwk_keys = find_property_by_name(json, "keys"); + if (jwk_keys == NULL) { + /* Use the google proprietary format which is: + { : , : , ... } */ + const grpc_json *cur = find_property_by_name(json, header_kid); + if (cur == NULL) return NULL; + return extract_pkey_from_x509(cur->value); + } + + if (jwk_keys->type != GRPC_JSON_ARRAY) { + gpr_log(GPR_ERROR, + "Unexpected value type of keys property in jwks key set."); + return NULL; + } + /* Key format is specified in: + https://tools.ietf.org/html/rfc7518#section-6. */ + for (jkey = jwk_keys->child; jkey != NULL; jkey = jkey->next) { + grpc_json *key_prop; + const char *alg = NULL; + const char *kid = NULL; + const char *kty = NULL; + + if (jkey->type != GRPC_JSON_OBJECT) continue; + for (key_prop = jkey->child; key_prop != NULL; key_prop = key_prop->next) { + if (strcmp(key_prop->key, "alg") == 0 && + key_prop->type == GRPC_JSON_STRING) { + alg = key_prop->value; + } else if (strcmp(key_prop->key, "kid") == 0 && + key_prop->type == GRPC_JSON_STRING) { + kid = key_prop->value; + } else if (strcmp(key_prop->key, "kty") == 0 && + key_prop->type == GRPC_JSON_STRING) { + kty = key_prop->value; + } + } + if (alg != NULL && kid != NULL && kty != NULL && + strcmp(kid, header_kid) == 0 && strcmp(alg, header_alg) == 0) { + return pkey_from_jwk(jkey, kty); + } + } + gpr_log(GPR_ERROR, + "Could not find matching key in key set for kid=%s and alg=%s", + header_kid, header_alg); + return NULL; +} + +static int verify_jwt_signature(EVP_PKEY *key, const char *alg, + gpr_slice signature, gpr_slice signed_data) { + EVP_MD_CTX *md_ctx = EVP_MD_CTX_create(); + const EVP_MD *md = evp_md_from_alg(alg); + int result = 0; + + GPR_ASSERT(md != NULL); /* Checked before. */ + if (md_ctx == NULL) { + gpr_log(GPR_ERROR, "Could not create EVP_MD_CTX."); + goto end; + } + if (EVP_DigestVerifyInit(md_ctx, NULL, md, NULL, key) != 1) { + gpr_log(GPR_ERROR, "EVP_DigestVerifyInit failed."); + goto end; + } + if (EVP_DigestVerifyUpdate(md_ctx, GPR_SLICE_START_PTR(signed_data), + GPR_SLICE_LENGTH(signed_data)) != 1) { + gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed."); + goto end; + } + if (EVP_DigestVerifyFinal(md_ctx, GPR_SLICE_START_PTR(signature), + GPR_SLICE_LENGTH(signature)) != 1) { + gpr_log(GPR_ERROR, "JWT signature verification failed."); + goto end; + } + result = 1; + +end: + if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); + return result; +} + +static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data, + const grpc_httpcli_response *response) { + grpc_json *json = json_from_http(response); + verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data; + EVP_PKEY *verification_key = NULL; + grpc_jwt_verifier_status status = GRPC_JWT_VERIFIER_GENERIC_ERROR; + grpc_jwt_claims *claims = NULL; + + if (json == NULL) { + status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR; + goto end; + } + verification_key = + find_verification_key(json, ctx->header->alg, ctx->header->kid); + if (verification_key == NULL) { + gpr_log(GPR_ERROR, "Could not find verification key with kid %s.", + ctx->header->kid); + status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR; + goto end; + } + + if (!verify_jwt_signature(verification_key, ctx->header->alg, ctx->signature, + ctx->signed_data)) { + status = GRPC_JWT_VERIFIER_BAD_SIGNATURE; + goto end; + } + + status = grpc_jwt_claims_check(ctx->claims, ctx->audience); + if (status == GRPC_JWT_VERIFIER_OK) { + /* Pass ownership. */ + claims = ctx->claims; + ctx->claims = NULL; + } + +end: + if (json != NULL) grpc_json_destroy(json); + if (verification_key != NULL) EVP_PKEY_free(verification_key); + ctx->user_cb(ctx->user_data, status, claims); + verifier_cb_ctx_destroy(ctx); +} + +static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data, + const grpc_httpcli_response *response) { + const grpc_json *cur; + grpc_json *json = json_from_http(response); + verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data; + grpc_httpcli_request req; + const char *jwks_uri; + + /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time. */ + if (json == NULL) goto error; + cur = find_property_by_name(json, "jwks_uri"); + if (cur == NULL) { + gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config."); + goto error; + } + jwks_uri = validate_string_field(cur, "jwks_uri"); + if (jwks_uri == NULL) goto error; + if (strstr(jwks_uri, "https://") != jwks_uri) { + gpr_log(GPR_ERROR, "Invalid non https jwks_uri: %s.", jwks_uri); + goto error; + } + jwks_uri += 8; + req.handshaker = &grpc_httpcli_ssl; + req.host = gpr_strdup(jwks_uri); + req.http.path = strchr(jwks_uri, '/'); + if (req.http.path == NULL) { + req.http.path = ""; + } else { + *(req.host + (req.http.path - jwks_uri)) = '\0'; + } + grpc_httpcli_get( + exec_ctx, &ctx->verifier->http_ctx, ctx->pollset, &req, + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay), + on_keys_retrieved, ctx); + grpc_json_destroy(json); + gpr_free(req.host); + return; + +error: + if (json != NULL) grpc_json_destroy(json); + ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL); + verifier_cb_ctx_destroy(ctx); +} + +static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v, + const char *email_domain) { + size_t i; + if (v->mappings == NULL) return NULL; + for (i = 0; i < v->num_mappings; i++) { + if (strcmp(email_domain, v->mappings[i].email_domain) == 0) { + return &v->mappings[i]; + } + } + return NULL; +} + +static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain, + const char *key_url_prefix) { + email_key_mapping *mapping = verifier_get_mapping(v, email_domain); + GPR_ASSERT(v->num_mappings < v->allocated_mappings); + if (mapping != NULL) { + gpr_free(mapping->key_url_prefix); + mapping->key_url_prefix = gpr_strdup(key_url_prefix); + return; + } + v->mappings[v->num_mappings].email_domain = gpr_strdup(email_domain); + v->mappings[v->num_mappings].key_url_prefix = gpr_strdup(key_url_prefix); + v->num_mappings++; + GPR_ASSERT(v->num_mappings <= v->allocated_mappings); +} + +/* Takes ownership of ctx. */ +static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx, + verifier_cb_ctx *ctx) { + const char *at_sign; + grpc_httpcli_response_cb http_cb; + char *path_prefix = NULL; + const char *iss; + grpc_httpcli_request req; + memset(&req, 0, sizeof(grpc_httpcli_request)); + req.handshaker = &grpc_httpcli_ssl; + + GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL); + iss = ctx->claims->iss; + if (ctx->header->kid == NULL) { + gpr_log(GPR_ERROR, "Missing kid in jose header."); + goto error; + } + if (iss == NULL) { + gpr_log(GPR_ERROR, "Missing iss in claims."); + goto error; + } + + /* This code relies on: + https://openid.net/specs/openid-connect-discovery-1_0.html + Nobody seems to implement the account/email/webfinger part 2. of the spec + so we will rely instead on email/url mappings if we detect such an issuer. + Part 4, on the other hand is implemented by both google and salesforce. */ + + /* Very non-sophisticated way to detect an email address. Should be good + enough for now... */ + at_sign = strchr(iss, '@'); + if (at_sign != NULL) { + email_key_mapping *mapping; + const char *email_domain = at_sign + 1; + GPR_ASSERT(ctx->verifier != NULL); + mapping = verifier_get_mapping(ctx->verifier, email_domain); + if (mapping == NULL) { + gpr_log(GPR_ERROR, "Missing mapping for issuer email."); + goto error; + } + req.host = gpr_strdup(mapping->key_url_prefix); + path_prefix = strchr(req.host, '/'); + if (path_prefix == NULL) { + gpr_asprintf(&req.http.path, "/%s", iss); + } else { + *(path_prefix++) = '\0'; + gpr_asprintf(&req.http.path, "/%s/%s", path_prefix, iss); + } + http_cb = on_keys_retrieved; + } else { + req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss); + path_prefix = strchr(req.host, '/'); + if (path_prefix == NULL) { + req.http.path = gpr_strdup(GRPC_OPENID_CONFIG_URL_SUFFIX); + } else { + *(path_prefix++) = 0; + gpr_asprintf(&req.http.path, "/%s%s", path_prefix, + GRPC_OPENID_CONFIG_URL_SUFFIX); + } + http_cb = on_openid_config_retrieved; + } + + grpc_httpcli_get( + exec_ctx, &ctx->verifier->http_ctx, ctx->pollset, &req, + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay), + http_cb, ctx); + gpr_free(req.host); + gpr_free(req.http.path); + return; + +error: + ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL); + verifier_cb_ctx_destroy(ctx); +} + +void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, + grpc_jwt_verifier *verifier, + grpc_pollset *pollset, const char *jwt, + const char *audience, + grpc_jwt_verification_done_cb cb, + void *user_data) { + const char *dot = NULL; + grpc_json *json; + jose_header *header = NULL; + grpc_jwt_claims *claims = NULL; + gpr_slice header_buffer; + gpr_slice claims_buffer; + gpr_slice signature; + size_t signed_jwt_len; + const char *cur = jwt; + + GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL); + dot = strchr(cur, '.'); + if (dot == NULL) goto error; + json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &header_buffer); + if (json == NULL) goto error; + header = jose_header_from_json(json, header_buffer); + if (header == NULL) goto error; + + cur = dot + 1; + dot = strchr(cur, '.'); + if (dot == NULL) goto error; + json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer); + if (json == NULL) goto error; + claims = grpc_jwt_claims_from_json(json, claims_buffer); + if (claims == NULL) goto error; + + signed_jwt_len = (size_t)(dot - jwt); + cur = dot + 1; + signature = grpc_base64_decode(cur, 1); + if (GPR_SLICE_IS_EMPTY(signature)) goto error; + retrieve_key_and_verify( + exec_ctx, + verifier_cb_ctx_create(verifier, pollset, header, claims, audience, + signature, jwt, signed_jwt_len, user_data, cb)); + return; + +error: + if (header != NULL) jose_header_destroy(header); + if (claims != NULL) grpc_jwt_claims_destroy(claims); + cb(user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL); +} + +grpc_jwt_verifier *grpc_jwt_verifier_create( + const grpc_jwt_verifier_email_domain_key_url_mapping *mappings, + size_t num_mappings) { + grpc_jwt_verifier *v = gpr_malloc(sizeof(grpc_jwt_verifier)); + memset(v, 0, sizeof(grpc_jwt_verifier)); + grpc_httpcli_context_init(&v->http_ctx); + + /* We know at least of one mapping. */ + v->allocated_mappings = 1 + num_mappings; + v->mappings = gpr_malloc(v->allocated_mappings * sizeof(email_key_mapping)); + verifier_put_mapping(v, GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN, + GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX); + /* User-Provided mappings. */ + if (mappings != NULL) { + size_t i; + for (i = 0; i < num_mappings; i++) { + verifier_put_mapping(v, mappings[i].email_domain, + mappings[i].key_url_prefix); + } + } + return v; +} + +void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) { + size_t i; + if (v == NULL) return; + grpc_httpcli_context_destroy(&v->http_ctx); + if (v->mappings != NULL) { + for (i = 0; i < v->num_mappings; i++) { + gpr_free(v->mappings[i].email_domain); + gpr_free(v->mappings[i].key_url_prefix); + } + gpr_free(v->mappings); + } + gpr_free(v); +} diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.h b/src/core/lib/security/credentials/jwt/jwt_verifier.h new file mode 100644 index 0000000000..b0f6d1c240 --- /dev/null +++ b/src/core/lib/security/credentials/jwt/jwt_verifier.h @@ -0,0 +1,136 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H + +#include "src/core/lib/iomgr/pollset.h" +#include "src/core/lib/json/json.h" + +#include +#include + +/* --- Constants. --- */ + +#define GRPC_OPENID_CONFIG_URL_SUFFIX "/.well-known/openid-configuration" +#define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN \ + "developer.gserviceaccount.com" +#define GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX \ + "www.googleapis.com/robot/v1/metadata/x509" + +/* --- grpc_jwt_verifier_status. --- */ + +typedef enum { + GRPC_JWT_VERIFIER_OK = 0, + GRPC_JWT_VERIFIER_BAD_SIGNATURE, + GRPC_JWT_VERIFIER_BAD_FORMAT, + GRPC_JWT_VERIFIER_BAD_AUDIENCE, + GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, + GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE, + GRPC_JWT_VERIFIER_GENERIC_ERROR +} grpc_jwt_verifier_status; + +const char *grpc_jwt_verifier_status_to_string(grpc_jwt_verifier_status status); + +/* --- grpc_jwt_claims. --- */ + +typedef struct grpc_jwt_claims grpc_jwt_claims; + +void grpc_jwt_claims_destroy(grpc_jwt_claims *claims); + +/* Returns the whole JSON tree of the claims. */ +const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims); + +/* Access to registered claims in https://tools.ietf.org/html/rfc7519#page-9 */ +const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims); +const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims); +const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims); +const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims); +gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims); +gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims); +gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims); + +/* --- grpc_jwt_verifier. --- */ + +typedef struct grpc_jwt_verifier grpc_jwt_verifier; + +typedef struct { + /* The email domain is the part after the @ sign. */ + const char *email_domain; + + /* The key url prefix will be used to get the public key from the issuer: + https:/// + Therefore the key_url_prefix must NOT contain https://. */ + const char *key_url_prefix; +} grpc_jwt_verifier_email_domain_key_url_mapping; + +/* Globals to control the verifier. Not thread-safe. */ +extern gpr_timespec grpc_jwt_verifier_clock_skew; +extern gpr_timespec grpc_jwt_verifier_max_delay; + +/* The verifier can be created with some custom mappings to help with key + discovery in the case where the issuer is an email address. + mappings can be NULL in which case num_mappings MUST be 0. + A verifier object has one built-in mapping (unless overridden): + GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN -> + GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX.*/ +grpc_jwt_verifier *grpc_jwt_verifier_create( + const grpc_jwt_verifier_email_domain_key_url_mapping *mappings, + size_t num_mappings); + +/*The verifier must not be destroyed if there are still outstanding callbacks.*/ +void grpc_jwt_verifier_destroy(grpc_jwt_verifier *verifier); + +/* User provided callback that will be called when the verification of the JWT + is done (maybe in another thread). + It is the responsibility of the callee to call grpc_jwt_claims_destroy on + the claims. */ +typedef void (*grpc_jwt_verification_done_cb)(void *user_data, + grpc_jwt_verifier_status status, + grpc_jwt_claims *claims); + +/* Verifies for the JWT for the given expected audience. */ +void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, + grpc_jwt_verifier *verifier, + grpc_pollset *pollset, const char *jwt, + const char *audience, + grpc_jwt_verification_done_cb cb, + void *user_data); + +/* --- TESTING ONLY exposed functions. --- */ + +grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer); +grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims, + const char *audience); + +#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H */ diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c new file mode 100644 index 0000000000..0984d1f53f --- /dev/null +++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c @@ -0,0 +1,430 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" + +#include + +#include "src/core/lib/security/util/json_util.h" +#include "src/core/lib/surface/api_trace.h" + +#include +#include +#include + +// +// Auth Refresh Token. +// + +int grpc_auth_refresh_token_is_valid( + const grpc_auth_refresh_token *refresh_token) { + return (refresh_token != NULL) && + strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID); +} + +grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json( + const grpc_json *json) { + grpc_auth_refresh_token result; + const char *prop_value; + int success = 0; + + memset(&result, 0, sizeof(grpc_auth_refresh_token)); + result.type = GRPC_AUTH_JSON_TYPE_INVALID; + if (json == NULL) { + gpr_log(GPR_ERROR, "Invalid json."); + goto end; + } + + prop_value = grpc_json_get_string_property(json, "type"); + if (prop_value == NULL || + strcmp(prop_value, GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER)) { + goto end; + } + result.type = GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER; + + if (!grpc_copy_json_string_property(json, "client_secret", + &result.client_secret) || + !grpc_copy_json_string_property(json, "client_id", &result.client_id) || + !grpc_copy_json_string_property(json, "refresh_token", + &result.refresh_token)) { + goto end; + } + success = 1; + +end: + if (!success) grpc_auth_refresh_token_destruct(&result); + return result; +} + +grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( + const char *json_string) { + char *scratchpad = gpr_strdup(json_string); + grpc_json *json = grpc_json_parse_string(scratchpad); + grpc_auth_refresh_token result = + grpc_auth_refresh_token_create_from_json(json); + if (json != NULL) grpc_json_destroy(json); + gpr_free(scratchpad); + return result; +} + +void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token) { + if (refresh_token == NULL) return; + refresh_token->type = GRPC_AUTH_JSON_TYPE_INVALID; + if (refresh_token->client_id != NULL) { + gpr_free(refresh_token->client_id); + refresh_token->client_id = NULL; + } + if (refresh_token->client_secret != NULL) { + gpr_free(refresh_token->client_secret); + refresh_token->client_secret = NULL; + } + if (refresh_token->refresh_token != NULL) { + gpr_free(refresh_token->refresh_token); + refresh_token->refresh_token = NULL; + } +} + +// +// Oauth2 Token Fetcher credentials. +// + +static void oauth2_token_fetcher_destruct(grpc_call_credentials *creds) { + grpc_oauth2_token_fetcher_credentials *c = + (grpc_oauth2_token_fetcher_credentials *)creds; + grpc_credentials_md_store_unref(c->access_token_md); + gpr_mu_destroy(&c->mu); + grpc_httpcli_context_destroy(&c->httpcli_context); +} + +grpc_credentials_status +grpc_oauth2_token_fetcher_credentials_parse_server_response( + const grpc_http_response *response, grpc_credentials_md_store **token_md, + gpr_timespec *token_lifetime) { + char *null_terminated_body = NULL; + char *new_access_token = NULL; + grpc_credentials_status status = GRPC_CREDENTIALS_OK; + grpc_json *json = NULL; + + if (response == NULL) { + gpr_log(GPR_ERROR, "Received NULL response."); + status = GRPC_CREDENTIALS_ERROR; + goto end; + } + + if (response->body_length > 0) { + null_terminated_body = gpr_malloc(response->body_length + 1); + null_terminated_body[response->body_length] = '\0'; + memcpy(null_terminated_body, response->body, response->body_length); + } + + if (response->status != 200) { + gpr_log(GPR_ERROR, "Call to http server ended with error %d [%s].", + response->status, + null_terminated_body != NULL ? null_terminated_body : ""); + status = GRPC_CREDENTIALS_ERROR; + goto end; + } else { + grpc_json *access_token = NULL; + grpc_json *token_type = NULL; + grpc_json *expires_in = NULL; + grpc_json *ptr; + json = grpc_json_parse_string(null_terminated_body); + if (json == NULL) { + gpr_log(GPR_ERROR, "Could not parse JSON from %s", null_terminated_body); + status = GRPC_CREDENTIALS_ERROR; + goto end; + } + if (json->type != GRPC_JSON_OBJECT) { + gpr_log(GPR_ERROR, "Response should be a JSON object"); + status = GRPC_CREDENTIALS_ERROR; + goto end; + } + for (ptr = json->child; ptr; ptr = ptr->next) { + if (strcmp(ptr->key, "access_token") == 0) { + access_token = ptr; + } else if (strcmp(ptr->key, "token_type") == 0) { + token_type = ptr; + } else if (strcmp(ptr->key, "expires_in") == 0) { + expires_in = ptr; + } + } + if (access_token == NULL || access_token->type != GRPC_JSON_STRING) { + gpr_log(GPR_ERROR, "Missing or invalid access_token in JSON."); + status = GRPC_CREDENTIALS_ERROR; + goto end; + } + if (token_type == NULL || token_type->type != GRPC_JSON_STRING) { + gpr_log(GPR_ERROR, "Missing or invalid token_type in JSON."); + status = GRPC_CREDENTIALS_ERROR; + goto end; + } + if (expires_in == NULL || expires_in->type != GRPC_JSON_NUMBER) { + gpr_log(GPR_ERROR, "Missing or invalid expires_in in JSON."); + status = GRPC_CREDENTIALS_ERROR; + goto end; + } + gpr_asprintf(&new_access_token, "%s %s", token_type->value, + access_token->value); + token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10); + token_lifetime->tv_nsec = 0; + token_lifetime->clock_type = GPR_TIMESPAN; + if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md); + *token_md = grpc_credentials_md_store_create(1); + grpc_credentials_md_store_add_cstrings( + *token_md, GRPC_AUTHORIZATION_METADATA_KEY, new_access_token); + status = GRPC_CREDENTIALS_OK; + } + +end: + if (status != GRPC_CREDENTIALS_OK && (*token_md != NULL)) { + grpc_credentials_md_store_unref(*token_md); + *token_md = NULL; + } + if (null_terminated_body != NULL) gpr_free(null_terminated_body); + if (new_access_token != NULL) gpr_free(new_access_token); + if (json != NULL) grpc_json_destroy(json); + return status; +} + +static void on_oauth2_token_fetcher_http_response( + grpc_exec_ctx *exec_ctx, void *user_data, + const grpc_http_response *response) { + grpc_credentials_metadata_request *r = + (grpc_credentials_metadata_request *)user_data; + grpc_oauth2_token_fetcher_credentials *c = + (grpc_oauth2_token_fetcher_credentials *)r->creds; + gpr_timespec token_lifetime; + grpc_credentials_status status; + + gpr_mu_lock(&c->mu); + status = grpc_oauth2_token_fetcher_credentials_parse_server_response( + response, &c->access_token_md, &token_lifetime); + if (status == GRPC_CREDENTIALS_OK) { + c->token_expiration = + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime); + r->cb(exec_ctx, r->user_data, c->access_token_md->entries, + c->access_token_md->num_entries, status); + } else { + c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); + r->cb(exec_ctx, r->user_data, NULL, 0, status); + } + gpr_mu_unlock(&c->mu); + grpc_credentials_metadata_request_destroy(r); +} + +static void oauth2_token_fetcher_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, + grpc_pollset *pollset, grpc_auth_metadata_context context, + grpc_credentials_metadata_cb cb, void *user_data) { + grpc_oauth2_token_fetcher_credentials *c = + (grpc_oauth2_token_fetcher_credentials *)creds; + gpr_timespec refresh_threshold = gpr_time_from_seconds( + GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN); + grpc_credentials_md_store *cached_access_token_md = NULL; + { + gpr_mu_lock(&c->mu); + if (c->access_token_md != NULL && + (gpr_time_cmp( + gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)), + refresh_threshold) > 0)) { + cached_access_token_md = + grpc_credentials_md_store_ref(c->access_token_md); + } + gpr_mu_unlock(&c->mu); + } + if (cached_access_token_md != NULL) { + cb(exec_ctx, user_data, cached_access_token_md->entries, + cached_access_token_md->num_entries, GRPC_CREDENTIALS_OK); + grpc_credentials_md_store_unref(cached_access_token_md); + } else { + c->fetch_func( + exec_ctx, + grpc_credentials_metadata_request_create(creds, cb, user_data), + &c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response, + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold)); + } +} + +static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c, + grpc_fetch_oauth2_func fetch_func) { + memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials)); + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; + gpr_ref_init(&c->base.refcount, 1); + gpr_mu_init(&c->mu); + c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); + c->fetch_func = fetch_func; + grpc_httpcli_context_init(&c->httpcli_context); +} + +// +// Google Compute Engine credentials. +// + +static grpc_call_credentials_vtable compute_engine_vtable = { + oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata}; + +static void compute_engine_fetch_oauth2( + grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req, + grpc_httpcli_context *httpcli_context, grpc_pollset *pollset, + grpc_httpcli_response_cb response_cb, gpr_timespec deadline) { + grpc_http_header header = {"Metadata-Flavor", "Google"}; + grpc_httpcli_request request; + memset(&request, 0, sizeof(grpc_httpcli_request)); + request.host = GRPC_COMPUTE_ENGINE_METADATA_HOST; + request.http.path = GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH; + request.http.hdr_count = 1; + request.http.hdrs = &header; + grpc_httpcli_get(exec_ctx, httpcli_context, pollset, &request, deadline, + response_cb, metadata_req); +} + +grpc_call_credentials *grpc_google_compute_engine_credentials_create( + void *reserved) { + grpc_oauth2_token_fetcher_credentials *c = + gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials)); + GRPC_API_TRACE("grpc_compute_engine_credentials_create(reserved=%p)", 1, + (reserved)); + GPR_ASSERT(reserved == NULL); + init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2); + c->base.vtable = &compute_engine_vtable; + return &c->base; +} + +// +// Google Refresh Token credentials. +// + +static void refresh_token_destruct(grpc_call_credentials *creds) { + grpc_google_refresh_token_credentials *c = + (grpc_google_refresh_token_credentials *)creds; + grpc_auth_refresh_token_destruct(&c->refresh_token); + oauth2_token_fetcher_destruct(&c->base.base); +} + +static grpc_call_credentials_vtable refresh_token_vtable = { + refresh_token_destruct, oauth2_token_fetcher_get_request_metadata}; + +static void refresh_token_fetch_oauth2( + grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req, + grpc_httpcli_context *httpcli_context, grpc_pollset *pollset, + grpc_httpcli_response_cb response_cb, gpr_timespec deadline) { + grpc_google_refresh_token_credentials *c = + (grpc_google_refresh_token_credentials *)metadata_req->creds; + grpc_http_header header = {"Content-Type", + "application/x-www-form-urlencoded"}; + grpc_httpcli_request request; + char *body = NULL; + gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING, + c->refresh_token.client_id, c->refresh_token.client_secret, + c->refresh_token.refresh_token); + memset(&request, 0, sizeof(grpc_httpcli_request)); + request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST; + request.http.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH; + request.http.hdr_count = 1; + request.http.hdrs = &header; + request.handshaker = &grpc_httpcli_ssl; + grpc_httpcli_post(exec_ctx, httpcli_context, pollset, &request, body, + strlen(body), deadline, response_cb, metadata_req); + gpr_free(body); +} + +grpc_call_credentials * +grpc_refresh_token_credentials_create_from_auth_refresh_token( + grpc_auth_refresh_token refresh_token) { + grpc_google_refresh_token_credentials *c; + if (!grpc_auth_refresh_token_is_valid(&refresh_token)) { + gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation"); + return NULL; + } + c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials)); + memset(c, 0, sizeof(grpc_google_refresh_token_credentials)); + init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2); + c->base.base.vtable = &refresh_token_vtable; + c->refresh_token = refresh_token; + return &c->base.base; +} + +grpc_call_credentials *grpc_google_refresh_token_credentials_create( + const char *json_refresh_token, void *reserved) { + GRPC_API_TRACE( + "grpc_refresh_token_credentials_create(json_refresh_token=%s, " + "reserved=%p)", + 2, (json_refresh_token, reserved)); + GPR_ASSERT(reserved == NULL); + return grpc_refresh_token_credentials_create_from_auth_refresh_token( + grpc_auth_refresh_token_create_from_string(json_refresh_token)); +} + +// +// Oauth2 Access Token credentials. +// + +static void access_token_destruct(grpc_call_credentials *creds) { + grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; + grpc_credentials_md_store_unref(c->access_token_md); +} + +static void access_token_get_request_metadata( + grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds, + grpc_pollset *pollset, grpc_auth_metadata_context context, + grpc_credentials_metadata_cb cb, void *user_data) { + grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; + cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK); +} + +static grpc_call_credentials_vtable access_token_vtable = { + access_token_destruct, access_token_get_request_metadata}; + +grpc_call_credentials *grpc_access_token_credentials_create( + const char *access_token, void *reserved) { + grpc_access_token_credentials *c = + gpr_malloc(sizeof(grpc_access_token_credentials)); + char *token_md_value; + GRPC_API_TRACE( + "grpc_access_token_credentials_create(access_token=%s, " + "reserved=%p)", + 2, (access_token, reserved)); + GPR_ASSERT(reserved == NULL); + memset(c, 0, sizeof(grpc_access_token_credentials)); + c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2; + c->base.vtable = &access_token_vtable; + gpr_ref_init(&c->base.refcount, 1); + c->access_token_md = grpc_credentials_md_store_create(1); + gpr_asprintf(&token_md_value, "Bearer %s", access_token); + grpc_credentials_md_store_add_cstrings( + c->access_token_md, GRPC_AUTHORIZATION_METADATA_KEY, token_md_value); + gpr_free(token_md_value); + return &c->base; +} + + diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h new file mode 100644 index 0000000000..6cdcc68514 --- /dev/null +++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h @@ -0,0 +1,111 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_CREDENTIALS_H + +#include "src/core/lib/json/json.h" +#include "src/core/lib/security/credentials/credentials.h" + +// auth_refresh_token parsing. +typedef struct { + const char *type; + char *client_id; + char *client_secret; + char *refresh_token; +} grpc_auth_refresh_token; + +/// Returns 1 if the object is valid, 0 otherwise. +int grpc_auth_refresh_token_is_valid( + const grpc_auth_refresh_token *refresh_token); + +/// Creates a refresh token object from string. Returns an invalid object if a +/// parsing error has been encountered. +grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( + const char *json_string); + +/// Creates a refresh token object from parsed json. Returns an invalid object +/// if a parsing error has been encountered. +grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json( + const grpc_json *json); + +/// Destructs the object. +void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token); + +// -- Oauth2 Token Fetcher credentials -- +// +// This object is a base for credentials that need to acquire an oauth2 token +// from an http service. + +typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx, + grpc_credentials_metadata_request *req, + grpc_httpcli_context *http_context, + grpc_pollset *pollset, + grpc_httpcli_response_cb response_cb, + gpr_timespec deadline); +typedef struct { + grpc_call_credentials base; + gpr_mu mu; + grpc_credentials_md_store *access_token_md; + gpr_timespec token_expiration; + grpc_httpcli_context httpcli_context; + grpc_fetch_oauth2_func fetch_func; +} grpc_oauth2_token_fetcher_credentials; + + +// Google refresh token credentials. +typedef struct { + grpc_oauth2_token_fetcher_credentials base; + grpc_auth_refresh_token refresh_token; +} grpc_google_refresh_token_credentials; + +// Access token credentials. +typedef struct { + grpc_call_credentials base; + grpc_credentials_md_store *access_token_md; +} grpc_access_token_credentials; + +// Private constructor for refresh token credentials from an already parsed +// refresh token. Takes ownership of the refresh token. +grpc_call_credentials * +grpc_refresh_token_credentials_create_from_auth_refresh_token( + grpc_auth_refresh_token token); + +// Exposed for testing only. +grpc_credentials_status +grpc_oauth2_token_fetcher_credentials_parse_server_response( + const struct grpc_http_response *response, + grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime); + +#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_CREDENTIALS_H + diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.c b/src/core/lib/security/credentials/plugin/plugin_credentials.c new file mode 100644 index 0000000000..b075e14551 --- /dev/null +++ b/src/core/lib/security/credentials/plugin/plugin_credentials.c @@ -0,0 +1,131 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/plugin/plugin_credentials.h" + +#include + +#include "src/core/lib/surface/api_trace.h" + +#include +#include +#include +#include + +typedef struct { + void *user_data; + grpc_credentials_metadata_cb cb; +} grpc_metadata_plugin_request; + +static void plugin_destruct(grpc_call_credentials *creds) { + grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds; + if (c->plugin.state != NULL && c->plugin.destroy != NULL) { + c->plugin.destroy(c->plugin.state); + } +} + +static void plugin_md_request_metadata_ready(void *request, + const grpc_metadata *md, + size_t num_md, + grpc_status_code status, + const char *error_details) { + /* called from application code */ + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request; + if (status != GRPC_STATUS_OK) { + if (error_details != NULL) { + gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s", + error_details); + } + r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR); + } else { + size_t i; + grpc_credentials_md *md_array = NULL; + if (num_md > 0) { + md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md)); + for (i = 0; i < num_md; i++) { + md_array[i].key = gpr_slice_from_copied_string(md[i].key); + md_array[i].value = + gpr_slice_from_copied_buffer(md[i].value, md[i].value_length); + } + } + r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK); + if (md_array != NULL) { + for (i = 0; i < num_md; i++) { + gpr_slice_unref(md_array[i].key); + gpr_slice_unref(md_array[i].value); + } + gpr_free(md_array); + } + } + gpr_free(r); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_credentials *creds, + grpc_pollset *pollset, + grpc_auth_metadata_context context, + grpc_credentials_metadata_cb cb, + void *user_data) { + grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds; + if (c->plugin.get_metadata != NULL) { + grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request)); + memset(request, 0, sizeof(*request)); + request->user_data = user_data; + request->cb = cb; + c->plugin.get_metadata(c->plugin.state, context, + plugin_md_request_metadata_ready, request); + } else { + cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK); + } +} + +static grpc_call_credentials_vtable plugin_vtable = { + plugin_destruct, plugin_get_request_metadata}; + +grpc_call_credentials *grpc_metadata_credentials_create_from_plugin( + grpc_metadata_credentials_plugin plugin, void *reserved) { + grpc_plugin_credentials *c = gpr_malloc(sizeof(*c)); + GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1, + (reserved)); + GPR_ASSERT(reserved == NULL); + memset(c, 0, sizeof(*c)); + c->base.type = plugin.type; + c->base.vtable = &plugin_vtable; + gpr_ref_init(&c->base.refcount, 1); + c->plugin = plugin; + return &c->base; +} + + diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.h b/src/core/lib/security/credentials/plugin/plugin_credentials.h new file mode 100644 index 0000000000..cdabbbd30f --- /dev/null +++ b/src/core/lib/security/credentials/plugin/plugin_credentials.h @@ -0,0 +1,48 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_CREDENTIALS_H + +#include "src/core/lib/security/credentials/credentials.h" + +typedef struct { + grpc_call_credentials base; + grpc_metadata_credentials_plugin plugin; + grpc_credentials_md_store *plugin_md; +} grpc_plugin_credentials; + +#endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_PLUGIN_CREDENTIALS_H + + + diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.c b/src/core/lib/security/credentials/ssl/ssl_credentials.c new file mode 100644 index 0000000000..ee8d2e4365 --- /dev/null +++ b/src/core/lib/security/credentials/ssl/ssl_credentials.c @@ -0,0 +1,244 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/credentials/ssl/ssl_credentials.h" + +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/http_client_filter.h" +#include "src/core/lib/surface/api_trace.h" + +#include +#include + +// +// Utils +// + +static void ssl_copy_key_material(const char *input, unsigned char **output, + size_t *output_size) { + *output_size = strlen(input); + *output = gpr_malloc(*output_size); + memcpy(*output, input, *output_size); +} + +// +// SSL Channel Credentials. +// + +static void ssl_destruct(grpc_channel_credentials *creds) { + grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; + if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); + if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key); + if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain); +} + +static grpc_security_status ssl_create_security_connector( + grpc_channel_credentials *creds, grpc_call_credentials *call_creds, + const char *target, const grpc_channel_args *args, + grpc_channel_security_connector **sc, grpc_channel_args **new_args) { + grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; + grpc_security_status status = GRPC_SECURITY_OK; + size_t i = 0; + const char *overridden_target_name = NULL; + grpc_arg new_arg; + + for (i = 0; args && i < args->num_args; i++) { + grpc_arg *arg = &args->args[i]; + if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 && + arg->type == GRPC_ARG_STRING) { + overridden_target_name = arg->value.string; + break; + } + } + status = grpc_ssl_channel_security_connector_create( + call_creds, &c->config, target, overridden_target_name, sc); + if (status != GRPC_SECURITY_OK) { + return status; + } + new_arg.type = GRPC_ARG_STRING; + new_arg.key = GRPC_ARG_HTTP2_SCHEME; + new_arg.value.string = "https"; + *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1); + return status; +} + +static grpc_channel_credentials_vtable ssl_vtable = { + ssl_destruct, ssl_create_security_connector}; + +static void ssl_build_config(const char *pem_root_certs, + grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, + grpc_ssl_config *config) { + if (pem_root_certs != NULL) { + ssl_copy_key_material(pem_root_certs, &config->pem_root_certs, + &config->pem_root_certs_size); + } + if (pem_key_cert_pair != NULL) { + GPR_ASSERT(pem_key_cert_pair->private_key != NULL); + GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL); + ssl_copy_key_material(pem_key_cert_pair->private_key, + &config->pem_private_key, + &config->pem_private_key_size); + ssl_copy_key_material(pem_key_cert_pair->cert_chain, + &config->pem_cert_chain, + &config->pem_cert_chain_size); + } +} + +grpc_channel_credentials *grpc_ssl_credentials_create( + const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, + void *reserved) { + grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials)); + GRPC_API_TRACE( + "grpc_ssl_credentials_create(pem_root_certs=%s, " + "pem_key_cert_pair=%p, " + "reserved=%p)", + 3, (pem_root_certs, pem_key_cert_pair, reserved)); + GPR_ASSERT(reserved == NULL); + memset(c, 0, sizeof(grpc_ssl_credentials)); + c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; + c->base.vtable = &ssl_vtable; + gpr_ref_init(&c->base.refcount, 1); + ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config); + return &c->base; +} + +// +// SSL Server Credentials. +// + +static void ssl_server_destruct(grpc_server_credentials *creds) { + grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds; + size_t i; + for (i = 0; i < c->config.num_key_cert_pairs; i++) { + if (c->config.pem_private_keys[i] != NULL) { + gpr_free(c->config.pem_private_keys[i]); + } + if (c->config.pem_cert_chains[i] != NULL) { + gpr_free(c->config.pem_cert_chains[i]); + } + } + if (c->config.pem_private_keys != NULL) gpr_free(c->config.pem_private_keys); + if (c->config.pem_private_keys_sizes != NULL) { + gpr_free(c->config.pem_private_keys_sizes); + } + if (c->config.pem_cert_chains != NULL) gpr_free(c->config.pem_cert_chains); + if (c->config.pem_cert_chains_sizes != NULL) { + gpr_free(c->config.pem_cert_chains_sizes); + } + if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); +} + + +static grpc_security_status ssl_server_create_security_connector( + grpc_server_credentials *creds, grpc_server_security_connector **sc) { + grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds; + return grpc_ssl_server_security_connector_create(&c->config, sc); +} + +static grpc_server_credentials_vtable ssl_server_vtable = { + ssl_server_destruct, ssl_server_create_security_connector}; + + +static void ssl_build_server_config( + const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, + size_t num_key_cert_pairs, + grpc_ssl_client_certificate_request_type client_certificate_request, + grpc_ssl_server_config *config) { + size_t i; + config->client_certificate_request = client_certificate_request; + if (pem_root_certs != NULL) { + ssl_copy_key_material(pem_root_certs, &config->pem_root_certs, + &config->pem_root_certs_size); + } + if (num_key_cert_pairs > 0) { + GPR_ASSERT(pem_key_cert_pairs != NULL); + config->pem_private_keys = + gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *)); + config->pem_cert_chains = + gpr_malloc(num_key_cert_pairs * sizeof(unsigned char *)); + config->pem_private_keys_sizes = + gpr_malloc(num_key_cert_pairs * sizeof(size_t)); + config->pem_cert_chains_sizes = + gpr_malloc(num_key_cert_pairs * sizeof(size_t)); + } + config->num_key_cert_pairs = num_key_cert_pairs; + for (i = 0; i < num_key_cert_pairs; i++) { + GPR_ASSERT(pem_key_cert_pairs[i].private_key != NULL); + GPR_ASSERT(pem_key_cert_pairs[i].cert_chain != NULL); + ssl_copy_key_material(pem_key_cert_pairs[i].private_key, + &config->pem_private_keys[i], + &config->pem_private_keys_sizes[i]); + ssl_copy_key_material(pem_key_cert_pairs[i].cert_chain, + &config->pem_cert_chains[i], + &config->pem_cert_chains_sizes[i]); + } +} + + +grpc_server_credentials *grpc_ssl_server_credentials_create( + const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, + size_t num_key_cert_pairs, int force_client_auth, void *reserved) { + return grpc_ssl_server_credentials_create_ex( + pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs, + force_client_auth + ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY + : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, + reserved); +} + +grpc_server_credentials *grpc_ssl_server_credentials_create_ex( + const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, + size_t num_key_cert_pairs, + grpc_ssl_client_certificate_request_type client_certificate_request, + void *reserved) { + grpc_ssl_server_credentials *c = + gpr_malloc(sizeof(grpc_ssl_server_credentials)); + GRPC_API_TRACE( + "grpc_ssl_server_credentials_create_ex(" + "pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, " + "client_certificate_request=%d, reserved=%p)", + 5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs, + client_certificate_request, reserved)); + GPR_ASSERT(reserved == NULL); + memset(c, 0, sizeof(grpc_ssl_server_credentials)); + c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL; + gpr_ref_init(&c->base.refcount, 1); + c->base.vtable = &ssl_server_vtable; + ssl_build_server_config(pem_root_certs, pem_key_cert_pairs, + num_key_cert_pairs, client_certificate_request, + &c->config); + return &c->base; +} + diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.h b/src/core/lib/security/credentials/ssl/ssl_credentials.h new file mode 100644 index 0000000000..ea4bdabc04 --- /dev/null +++ b/src/core/lib/security/credentials/ssl/ssl_credentials.h @@ -0,0 +1,49 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H + +#include "src/core/lib/security/credentials/credentials.h" + +typedef struct { + grpc_channel_credentials base; + grpc_ssl_config config; +} grpc_ssl_credentials; + +typedef struct { + grpc_server_credentials base; + grpc_ssl_server_config config; +} grpc_ssl_server_credentials; + +#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_SSL_SSL_CREDENTIALS_H */ + diff --git a/src/core/lib/security/credentials_metadata.c b/src/core/lib/security/credentials_metadata.c deleted file mode 100644 index bd00194278..0000000000 --- a/src/core/lib/security/credentials_metadata.c +++ /dev/null @@ -1,101 +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 "src/core/lib/security/credentials.h" - -#include - -#include - -static void store_ensure_capacity(grpc_credentials_md_store *store) { - if (store->num_entries == store->allocated) { - store->allocated = (store->allocated == 0) ? 1 : store->allocated * 2; - store->entries = gpr_realloc( - store->entries, store->allocated * sizeof(grpc_credentials_md)); - } -} - -grpc_credentials_md_store *grpc_credentials_md_store_create( - size_t initial_capacity) { - grpc_credentials_md_store *store = - gpr_malloc(sizeof(grpc_credentials_md_store)); - memset(store, 0, sizeof(grpc_credentials_md_store)); - if (initial_capacity > 0) { - store->entries = gpr_malloc(initial_capacity * sizeof(grpc_credentials_md)); - store->allocated = initial_capacity; - } - gpr_ref_init(&store->refcount, 1); - return store; -} - -void grpc_credentials_md_store_add(grpc_credentials_md_store *store, - gpr_slice key, gpr_slice value) { - if (store == NULL) return; - store_ensure_capacity(store); - store->entries[store->num_entries].key = gpr_slice_ref(key); - store->entries[store->num_entries].value = gpr_slice_ref(value); - store->num_entries++; -} - -void grpc_credentials_md_store_add_cstrings(grpc_credentials_md_store *store, - const char *key, - const char *value) { - if (store == NULL) return; - store_ensure_capacity(store); - store->entries[store->num_entries].key = gpr_slice_from_copied_string(key); - store->entries[store->num_entries].value = - gpr_slice_from_copied_string(value); - store->num_entries++; -} - -grpc_credentials_md_store *grpc_credentials_md_store_ref( - grpc_credentials_md_store *store) { - if (store == NULL) return NULL; - gpr_ref(&store->refcount); - return store; -} - -void grpc_credentials_md_store_unref(grpc_credentials_md_store *store) { - if (store == NULL) return; - if (gpr_unref(&store->refcount)) { - if (store->entries != NULL) { - size_t i; - for (i = 0; i < store->num_entries; i++) { - gpr_slice_unref(store->entries[i].key); - gpr_slice_unref(store->entries[i].value); - } - gpr_free(store->entries); - } - gpr_free(store); - } -} diff --git a/src/core/lib/security/credentials_posix.c b/src/core/lib/security/credentials_posix.c deleted file mode 100644 index a07de182a0..0000000000 --- a/src/core/lib/security/credentials_posix.c +++ /dev/null @@ -1,61 +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 - -#ifdef GPR_POSIX_FILE - -#include "src/core/lib/security/credentials.h" - -#include -#include -#include - -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/string.h" - -char *grpc_get_well_known_google_credentials_file_path_impl(void) { - char *result = NULL; - char *home = gpr_getenv("HOME"); - if (home == NULL) { - gpr_log(GPR_ERROR, "Could not get HOME environment variable."); - return NULL; - } - gpr_asprintf(&result, "%s/.config/%s/%s", home, - GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY, - GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE); - gpr_free(home); - return result; -} - -#endif /* GPR_POSIX_FILE */ diff --git a/src/core/lib/security/credentials_win32.c b/src/core/lib/security/credentials_win32.c deleted file mode 100644 index d29847af38..0000000000 --- a/src/core/lib/security/credentials_win32.c +++ /dev/null @@ -1,61 +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 - -#ifdef GPR_WIN32 - -#include "src/core/lib/security/credentials.h" - -#include -#include -#include - -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/string.h" - -char *grpc_get_well_known_google_credentials_file_path_impl(void) { - char *result = NULL; - char *appdata_path = gpr_getenv("APPDATA"); - if (appdata_path == NULL) { - gpr_log(GPR_ERROR, "Could not get APPDATA environment variable."); - return NULL; - } - gpr_asprintf(&result, "%s/%s/%s", appdata_path, - GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY, - GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE); - gpr_free(appdata_path); - return result; -} - -#endif /* GPR_WIN32 */ diff --git a/src/core/lib/security/google_default_credentials.c b/src/core/lib/security/google_default_credentials.c deleted file mode 100644 index 236f1d7fa7..0000000000 --- a/src/core/lib/security/google_default_credentials.c +++ /dev/null @@ -1,266 +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 "src/core/lib/security/credentials.h" - -#include - -#include -#include -#include - -#include "src/core/lib/http/httpcli.h" -#include "src/core/lib/http/parser.h" -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/load_file.h" -#include "src/core/lib/surface/api_trace.h" - -/* -- Constants. -- */ - -#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" - -/* -- Default credentials. -- */ - -static grpc_channel_credentials *default_credentials = NULL; -static int compute_engine_detection_done = 0; -static gpr_mu g_state_mu; -static gpr_mu *g_polling_mu; -static gpr_once g_once = GPR_ONCE_INIT; - -static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); } - -typedef struct { - grpc_pollset *pollset; - int is_done; - int success; -} compute_engine_detector; - -static void on_compute_engine_detection_http_response( - grpc_exec_ctx *exec_ctx, void *user_data, - const grpc_http_response *response) { - compute_engine_detector *detector = (compute_engine_detector *)user_data; - if (response != NULL && response->status == 200 && response->hdr_count > 0) { - /* Internet providers can return a generic response to all requests, so - it is necessary to check that metadata header is present also. */ - size_t i; - for (i = 0; i < response->hdr_count; i++) { - grpc_http_header *header = &response->hdrs[i]; - if (strcmp(header->key, "Metadata-Flavor") == 0 && - strcmp(header->value, "Google") == 0) { - detector->success = 1; - break; - } - } - } - gpr_mu_lock(g_polling_mu); - detector->is_done = 1; - grpc_pollset_kick(detector->pollset, NULL); - gpr_mu_unlock(g_polling_mu); -} - -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool s) { - grpc_pollset_destroy(p); -} - -static int is_stack_running_on_compute_engine(void) { - compute_engine_detector detector; - grpc_httpcli_request request; - grpc_httpcli_context context; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_closure destroy_closure; - - /* The http call is local. If it takes more than one sec, it is for sure not - on compute engine. */ - gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN); - - detector.pollset = gpr_malloc(grpc_pollset_size()); - grpc_pollset_init(detector.pollset, &g_polling_mu); - detector.is_done = 0; - detector.success = 0; - - memset(&request, 0, sizeof(grpc_httpcli_request)); - request.host = GRPC_COMPUTE_ENGINE_DETECTION_HOST; - request.http.path = "/"; - - grpc_httpcli_context_init(&context); - - grpc_httpcli_get( - &exec_ctx, &context, detector.pollset, &request, - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay), - on_compute_engine_detection_http_response, &detector); - - grpc_exec_ctx_finish(&exec_ctx); - - /* Block until we get the response. This is not ideal but this should only be - called once for the lifetime of the process by the default credentials. */ - gpr_mu_lock(g_polling_mu); - while (!detector.is_done) { - grpc_pollset_worker *worker = NULL; - grpc_pollset_work(&exec_ctx, detector.pollset, &worker, - gpr_now(GPR_CLOCK_MONOTONIC), - gpr_inf_future(GPR_CLOCK_MONOTONIC)); - } - gpr_mu_unlock(g_polling_mu); - - grpc_httpcli_context_destroy(&context); - grpc_closure_init(&destroy_closure, destroy_pollset, detector.pollset); - grpc_pollset_shutdown(&exec_ctx, detector.pollset, &destroy_closure); - grpc_exec_ctx_finish(&exec_ctx); - g_polling_mu = NULL; - - gpr_free(detector.pollset); - - return detector.success; -} - -/* Takes ownership of creds_path if not NULL. */ -static grpc_call_credentials *create_default_creds_from_path(char *creds_path) { - grpc_json *json = NULL; - grpc_auth_json_key key; - grpc_auth_refresh_token token; - grpc_call_credentials *result = NULL; - gpr_slice creds_data = gpr_empty_slice(); - int file_ok = 0; - if (creds_path == NULL) goto end; - creds_data = gpr_load_file(creds_path, 0, &file_ok); - if (!file_ok) goto end; - json = grpc_json_parse_string_with_len( - (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data)); - if (json == NULL) goto end; - - /* First, try an auth json key. */ - key = grpc_auth_json_key_create_from_json(json); - if (grpc_auth_json_key_is_valid(&key)) { - result = - grpc_service_account_jwt_access_credentials_create_from_auth_json_key( - key, grpc_max_auth_token_lifetime()); - goto end; - } - - /* Then try a refresh token if the auth json key was invalid. */ - token = grpc_auth_refresh_token_create_from_json(json); - if (grpc_auth_refresh_token_is_valid(&token)) { - result = - grpc_refresh_token_credentials_create_from_auth_refresh_token(token); - goto end; - } - -end: - if (creds_path != NULL) gpr_free(creds_path); - gpr_slice_unref(creds_data); - if (json != NULL) grpc_json_destroy(json); - return result; -} - -grpc_channel_credentials *grpc_google_default_credentials_create(void) { - grpc_channel_credentials *result = NULL; - grpc_call_credentials *call_creds = NULL; - - GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ()); - - gpr_once_init(&g_once, init_default_credentials); - - gpr_mu_lock(&g_state_mu); - - if (default_credentials != NULL) { - result = grpc_channel_credentials_ref(default_credentials); - goto end; - } - - /* First, try the environment variable. */ - call_creds = create_default_creds_from_path( - gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR)); - if (call_creds != NULL) goto end; - - /* Then the well-known file. */ - call_creds = create_default_creds_from_path( - grpc_get_well_known_google_credentials_file_path()); - if (call_creds != NULL) goto end; - - /* At last try to see if we're on compute engine (do the detection only once - since it requires a network test). */ - if (!compute_engine_detection_done) { - int need_compute_engine_creds = is_stack_running_on_compute_engine(); - compute_engine_detection_done = 1; - if (need_compute_engine_creds) { - call_creds = grpc_google_compute_engine_credentials_create(NULL); - } - } - -end: - if (result == NULL) { - if (call_creds != NULL) { - /* Blend with default ssl credentials and add a global reference so that - it - can be cached and re-served. */ - grpc_channel_credentials *ssl_creds = - grpc_ssl_credentials_create(NULL, NULL, NULL); - default_credentials = grpc_channel_credentials_ref( - grpc_composite_channel_credentials_create(ssl_creds, call_creds, - NULL)); - GPR_ASSERT(default_credentials != NULL); - grpc_channel_credentials_unref(ssl_creds); - grpc_call_credentials_unref(call_creds); - result = default_credentials; - } else { - gpr_log(GPR_ERROR, "Could not create google default credentials."); - } - } - gpr_mu_unlock(&g_state_mu); - return result; -} - -void grpc_flush_cached_google_default_credentials(void) { - gpr_once_init(&g_once, init_default_credentials); - gpr_mu_lock(&g_state_mu); - if (default_credentials != NULL) { - grpc_channel_credentials_unref(default_credentials); - default_credentials = NULL; - } - compute_engine_detection_done = 0; - gpr_mu_unlock(&g_state_mu); -} - -/* -- Well known credentials path. -- */ - -static grpc_well_known_credentials_path_getter creds_path_getter = NULL; - -char *grpc_get_well_known_google_credentials_file_path(void) { - if (creds_path_getter != NULL) return creds_path_getter(); - return grpc_get_well_known_google_credentials_file_path_impl(); -} - -void grpc_override_well_known_credentials_path_getter( - grpc_well_known_credentials_path_getter getter) { - creds_path_getter = getter; -} diff --git a/src/core/lib/security/handshake.c b/src/core/lib/security/handshake.c deleted file mode 100644 index d5fe0c7b7d..0000000000 --- a/src/core/lib/security/handshake.c +++ /dev/null @@ -1,336 +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 "src/core/lib/security/handshake.h" - -#include -#include - -#include -#include -#include -#include "src/core/lib/security/secure_endpoint.h" -#include "src/core/lib/security/security_context.h" - -#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256 - -typedef struct { - grpc_security_connector *connector; - tsi_handshaker *handshaker; - bool is_client_side; - unsigned char *handshake_buffer; - size_t handshake_buffer_size; - grpc_endpoint *wrapped_endpoint; - grpc_endpoint *secure_endpoint; - gpr_slice_buffer left_overs; - gpr_slice_buffer incoming; - gpr_slice_buffer outgoing; - grpc_security_handshake_done_cb cb; - void *user_data; - grpc_closure on_handshake_data_sent_to_peer; - grpc_closure on_handshake_data_received_from_peer; - grpc_auth_context *auth_context; -} grpc_security_handshake; - -static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, - void *setup, bool success); - -static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup, - bool success); - -static void security_connector_remove_handshake(grpc_security_handshake *h) { - GPR_ASSERT(!h->is_client_side); - grpc_security_connector_handshake_list *node; - grpc_security_connector_handshake_list *tmp; - grpc_server_security_connector *sc = - (grpc_server_security_connector *)h->connector; - gpr_mu_lock(&sc->mu); - node = sc->handshaking_handshakes; - if (node && node->handshake == h) { - sc->handshaking_handshakes = node->next; - gpr_free(node); - gpr_mu_unlock(&sc->mu); - return; - } - while (node) { - if (node->next->handshake == h) { - tmp = node->next; - node->next = node->next->next; - gpr_free(tmp); - gpr_mu_unlock(&sc->mu); - return; - } - node = node->next; - } - gpr_mu_unlock(&sc->mu); -} - -static void security_handshake_done(grpc_exec_ctx *exec_ctx, - grpc_security_handshake *h, - int is_success) { - if (!h->is_client_side) { - security_connector_remove_handshake(h); - } - if (is_success) { - h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint, - h->auth_context); - } else { - if (h->secure_endpoint != NULL) { - grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint); - grpc_endpoint_destroy(exec_ctx, h->secure_endpoint); - } else { - grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint); - } - h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL, NULL); - } - if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker); - if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer); - gpr_slice_buffer_destroy(&h->left_overs); - gpr_slice_buffer_destroy(&h->outgoing); - gpr_slice_buffer_destroy(&h->incoming); - GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake"); - GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake"); - gpr_free(h); -} - -static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data, - grpc_security_status status, - grpc_auth_context *auth_context) { - grpc_security_handshake *h = user_data; - tsi_frame_protector *protector; - tsi_result result; - if (status != GRPC_SECURITY_OK) { - gpr_log(GPR_ERROR, "Error checking peer."); - security_handshake_done(exec_ctx, h, 0); - return; - } - h->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "handshake"); - result = - tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Frame protector creation failed with error %s.", - tsi_result_to_string(result)); - security_handshake_done(exec_ctx, h, 0); - return; - } - h->secure_endpoint = - grpc_secure_endpoint_create(protector, h->wrapped_endpoint, - h->left_overs.slices, h->left_overs.count); - h->left_overs.count = 0; - h->left_overs.length = 0; - security_handshake_done(exec_ctx, h, 1); - return; -} - -static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) { - tsi_peer peer; - tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer); - - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Peer extraction failed with error %s", - tsi_result_to_string(result)); - security_handshake_done(exec_ctx, h, 0); - return; - } - grpc_security_connector_check_peer(exec_ctx, h->connector, peer, - on_peer_checked, h); -} - -static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx, - grpc_security_handshake *h) { - size_t offset = 0; - tsi_result result = TSI_OK; - gpr_slice to_send; - - do { - size_t to_send_size = h->handshake_buffer_size - offset; - result = tsi_handshaker_get_bytes_to_send_to_peer( - h->handshaker, h->handshake_buffer + offset, &to_send_size); - offset += to_send_size; - if (result == TSI_INCOMPLETE_DATA) { - h->handshake_buffer_size *= 2; - h->handshake_buffer = - gpr_realloc(h->handshake_buffer, h->handshake_buffer_size); - } - } while (result == TSI_INCOMPLETE_DATA); - - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshake failed with error %s", - tsi_result_to_string(result)); - security_handshake_done(exec_ctx, h, 0); - return; - } - - to_send = - gpr_slice_from_copied_buffer((const char *)h->handshake_buffer, offset); - gpr_slice_buffer_reset_and_unref(&h->outgoing); - gpr_slice_buffer_add(&h->outgoing, to_send); - /* TODO(klempner,jboeuf): This should probably use the client setup - deadline */ - grpc_endpoint_write(exec_ctx, h->wrapped_endpoint, &h->outgoing, - &h->on_handshake_data_sent_to_peer); -} - -static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, - void *handshake, - bool success) { - grpc_security_handshake *h = handshake; - size_t consumed_slice_size = 0; - tsi_result result = TSI_OK; - size_t i; - size_t num_left_overs; - int has_left_overs_in_current_slice = 0; - - if (!success) { - gpr_log(GPR_ERROR, "Read failed."); - security_handshake_done(exec_ctx, h, 0); - return; - } - - for (i = 0; i < h->incoming.count; i++) { - consumed_slice_size = GPR_SLICE_LENGTH(h->incoming.slices[i]); - result = tsi_handshaker_process_bytes_from_peer( - h->handshaker, GPR_SLICE_START_PTR(h->incoming.slices[i]), - &consumed_slice_size); - if (!tsi_handshaker_is_in_progress(h->handshaker)) break; - } - - if (tsi_handshaker_is_in_progress(h->handshaker)) { - /* We may need more data. */ - if (result == TSI_INCOMPLETE_DATA) { - grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming, - &h->on_handshake_data_received_from_peer); - return; - } else { - send_handshake_bytes_to_peer(exec_ctx, h); - return; - } - } - - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshake failed with error %s", - tsi_result_to_string(result)); - security_handshake_done(exec_ctx, h, 0); - return; - } - - /* Handshake is done and successful this point. */ - has_left_overs_in_current_slice = - (consumed_slice_size < GPR_SLICE_LENGTH(h->incoming.slices[i])); - num_left_overs = - (has_left_overs_in_current_slice ? 1 : 0) + h->incoming.count - i - 1; - if (num_left_overs == 0) { - check_peer(exec_ctx, h); - return; - } - - /* Put the leftovers in our buffer (ownership transfered). */ - if (has_left_overs_in_current_slice) { - gpr_slice_buffer_add( - &h->left_overs, - gpr_slice_split_tail(&h->incoming.slices[i], consumed_slice_size)); - gpr_slice_unref( - h->incoming.slices[i]); /* split_tail above increments refcount. */ - } - gpr_slice_buffer_addn( - &h->left_overs, &h->incoming.slices[i + 1], - num_left_overs - (size_t)has_left_overs_in_current_slice); - check_peer(exec_ctx, h); -} - -/* If handshake is NULL, the handshake is done. */ -static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, - void *handshake, bool success) { - grpc_security_handshake *h = handshake; - - /* Make sure that write is OK. */ - if (!success) { - gpr_log(GPR_ERROR, "Write failed."); - if (handshake != NULL) security_handshake_done(exec_ctx, h, 0); - return; - } - - /* We may be done. */ - if (tsi_handshaker_is_in_progress(h->handshaker)) { - /* TODO(klempner,jboeuf): This should probably use the client setup - deadline */ - grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming, - &h->on_handshake_data_received_from_peer); - } else { - check_peer(exec_ctx, h); - } -} - -void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx, - tsi_handshaker *handshaker, - grpc_security_connector *connector, - bool is_client_side, - grpc_endpoint *nonsecure_endpoint, - grpc_security_handshake_done_cb cb, - void *user_data) { - grpc_security_connector_handshake_list *handshake_node; - grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake)); - memset(h, 0, sizeof(grpc_security_handshake)); - h->handshaker = handshaker; - h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake"); - h->is_client_side = is_client_side; - h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE; - h->handshake_buffer = gpr_malloc(h->handshake_buffer_size); - h->wrapped_endpoint = nonsecure_endpoint; - h->user_data = user_data; - h->cb = cb; - grpc_closure_init(&h->on_handshake_data_sent_to_peer, - on_handshake_data_sent_to_peer, h); - grpc_closure_init(&h->on_handshake_data_received_from_peer, - on_handshake_data_received_from_peer, h); - gpr_slice_buffer_init(&h->left_overs); - gpr_slice_buffer_init(&h->outgoing); - gpr_slice_buffer_init(&h->incoming); - if (!is_client_side) { - grpc_server_security_connector *server_connector = - (grpc_server_security_connector *)connector; - handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list)); - handshake_node->handshake = h; - gpr_mu_lock(&server_connector->mu); - handshake_node->next = server_connector->handshaking_handshakes; - server_connector->handshaking_handshakes = handshake_node; - gpr_mu_unlock(&server_connector->mu); - } - send_handshake_bytes_to_peer(exec_ctx, h); -} - -void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, - void *handshake) { - grpc_security_handshake *h = handshake; - grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint); -} diff --git a/src/core/lib/security/handshake.h b/src/core/lib/security/handshake.h deleted file mode 100644 index f34476ed49..0000000000 --- a/src/core/lib/security/handshake.h +++ /dev/null @@ -1,51 +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. - * - */ - -#ifndef GRPC_CORE_LIB_SECURITY_HANDSHAKE_H -#define GRPC_CORE_LIB_SECURITY_HANDSHAKE_H - -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/security/security_connector.h" - -/* Calls the callback upon completion. Takes owership of handshaker. */ -void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx, - tsi_handshaker *handshaker, - grpc_security_connector *connector, - bool is_client_side, - grpc_endpoint *nonsecure_endpoint, - grpc_security_handshake_done_cb cb, - void *user_data); - -void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, void *handshake); - -#endif /* GRPC_CORE_LIB_SECURITY_HANDSHAKE_H */ diff --git a/src/core/lib/security/json_token.c b/src/core/lib/security/json_token.c deleted file mode 100644 index d5bc2c8d60..0000000000 --- a/src/core/lib/security/json_token.c +++ /dev/null @@ -1,411 +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 "src/core/lib/security/json_token.h" - -#include - -#include -#include -#include - -#include "src/core/lib/security/b64.h" -#include "src/core/lib/support/string.h" - -#include -#include -#include - -/* --- Constants. --- */ - -/* 1 hour max. */ -gpr_timespec grpc_max_auth_token_lifetime() { - gpr_timespec out; - out.tv_sec = 3600; - out.tv_nsec = 0; - out.clock_type = GPR_TIMESPAN; - return out; -} - -#define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256" -#define GRPC_JWT_TYPE "JWT" - -/* --- Override for testing. --- */ - -static grpc_jwt_encode_and_sign_override g_jwt_encode_and_sign_override = NULL; - -/* --- grpc_auth_json_key. --- */ - -static const char *json_get_string_property(const grpc_json *json, - const char *prop_name) { - grpc_json *child; - for (child = json->child; child != NULL; child = child->next) { - if (strcmp(child->key, prop_name) == 0) break; - } - if (child == NULL || child->type != GRPC_JSON_STRING) { - gpr_log(GPR_ERROR, "Invalid or missing %s property.", prop_name); - return NULL; - } - return child->value; -} - -static int set_json_key_string_property(const grpc_json *json, - const char *prop_name, - char **json_key_field) { - const char *prop_value = json_get_string_property(json, prop_name); - if (prop_value == NULL) return 0; - *json_key_field = gpr_strdup(prop_value); - return 1; -} - -int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key) { - return (json_key != NULL) && - strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID); -} - -grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json) { - grpc_auth_json_key result; - BIO *bio = NULL; - const char *prop_value; - int success = 0; - - memset(&result, 0, sizeof(grpc_auth_json_key)); - result.type = GRPC_AUTH_JSON_TYPE_INVALID; - if (json == NULL) { - gpr_log(GPR_ERROR, "Invalid json."); - goto end; - } - - prop_value = json_get_string_property(json, "type"); - if (prop_value == NULL || - strcmp(prop_value, GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT)) { - goto end; - } - result.type = GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT; - - if (!set_json_key_string_property(json, "private_key_id", - &result.private_key_id) || - !set_json_key_string_property(json, "client_id", &result.client_id) || - !set_json_key_string_property(json, "client_email", - &result.client_email)) { - goto end; - } - - prop_value = json_get_string_property(json, "private_key"); - if (prop_value == NULL) { - goto end; - } - bio = BIO_new(BIO_s_mem()); - success = BIO_puts(bio, prop_value); - if ((success < 0) || ((size_t)success != strlen(prop_value))) { - gpr_log(GPR_ERROR, "Could not write into openssl BIO."); - goto end; - } - result.private_key = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, ""); - if (result.private_key == NULL) { - gpr_log(GPR_ERROR, "Could not deserialize private key."); - goto end; - } - success = 1; - -end: - if (bio != NULL) BIO_free(bio); - if (!success) grpc_auth_json_key_destruct(&result); - return result; -} - -grpc_auth_json_key grpc_auth_json_key_create_from_string( - const char *json_string) { - char *scratchpad = gpr_strdup(json_string); - grpc_json *json = grpc_json_parse_string(scratchpad); - grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json); - if (json != NULL) grpc_json_destroy(json); - gpr_free(scratchpad); - return result; -} - -void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key) { - if (json_key == NULL) return; - json_key->type = GRPC_AUTH_JSON_TYPE_INVALID; - if (json_key->client_id != NULL) { - gpr_free(json_key->client_id); - json_key->client_id = NULL; - } - if (json_key->private_key_id != NULL) { - gpr_free(json_key->private_key_id); - json_key->private_key_id = NULL; - } - if (json_key->client_email != NULL) { - gpr_free(json_key->client_email); - json_key->client_email = NULL; - } - if (json_key->private_key != NULL) { - RSA_free(json_key->private_key); - json_key->private_key = NULL; - } -} - -/* --- jwt encoding and signature. --- */ - -static grpc_json *create_child(grpc_json *brother, grpc_json *parent, - const char *key, const char *value, - grpc_json_type type) { - grpc_json *child = grpc_json_create(type); - if (brother) brother->next = child; - if (!parent->child) parent->child = child; - child->parent = parent; - child->value = value; - child->key = key; - return child; -} - -static char *encoded_jwt_header(const char *key_id, const char *algorithm) { - grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT); - grpc_json *child = NULL; - char *json_str = NULL; - char *result = NULL; - - child = create_child(NULL, json, "alg", algorithm, GRPC_JSON_STRING); - child = create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING); - create_child(child, json, "kid", key_id, GRPC_JSON_STRING); - - json_str = grpc_json_dump_to_string(json, 0); - result = grpc_base64_encode(json_str, strlen(json_str), 1, 0); - gpr_free(json_str); - grpc_json_destroy(json); - return result; -} - -static char *encoded_jwt_claim(const grpc_auth_json_key *json_key, - const char *audience, - gpr_timespec token_lifetime, const char *scope) { - grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT); - grpc_json *child = NULL; - char *json_str = NULL; - char *result = NULL; - gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); - gpr_timespec expiration = gpr_time_add(now, token_lifetime); - char now_str[GPR_LTOA_MIN_BUFSIZE]; - char expiration_str[GPR_LTOA_MIN_BUFSIZE]; - if (gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime()) > 0) { - gpr_log(GPR_INFO, "Cropping token lifetime to maximum allowed value."); - expiration = gpr_time_add(now, grpc_max_auth_token_lifetime()); - } - int64_ttoa(now.tv_sec, now_str); - int64_ttoa(expiration.tv_sec, expiration_str); - - child = - create_child(NULL, json, "iss", json_key->client_email, GRPC_JSON_STRING); - if (scope != NULL) { - child = create_child(child, json, "scope", scope, GRPC_JSON_STRING); - } else { - /* Unscoped JWTs need a sub field. */ - child = create_child(child, json, "sub", json_key->client_email, - GRPC_JSON_STRING); - } - - child = create_child(child, json, "aud", audience, GRPC_JSON_STRING); - child = create_child(child, json, "iat", now_str, GRPC_JSON_NUMBER); - create_child(child, json, "exp", expiration_str, GRPC_JSON_NUMBER); - - json_str = grpc_json_dump_to_string(json, 0); - result = grpc_base64_encode(json_str, strlen(json_str), 1, 0); - gpr_free(json_str); - grpc_json_destroy(json); - return result; -} - -static char *dot_concat_and_free_strings(char *str1, char *str2) { - size_t str1_len = strlen(str1); - size_t str2_len = strlen(str2); - size_t result_len = str1_len + 1 /* dot */ + str2_len; - char *result = gpr_malloc(result_len + 1 /* NULL terminated */); - char *current = result; - memcpy(current, str1, str1_len); - current += str1_len; - *(current++) = '.'; - memcpy(current, str2, str2_len); - current += str2_len; - GPR_ASSERT(current >= result); - GPR_ASSERT((uintptr_t)(current - result) == result_len); - *current = '\0'; - gpr_free(str1); - gpr_free(str2); - return result; -} - -const EVP_MD *openssl_digest_from_algorithm(const char *algorithm) { - if (strcmp(algorithm, GRPC_JWT_RSA_SHA256_ALGORITHM) == 0) { - return EVP_sha256(); - } else { - gpr_log(GPR_ERROR, "Unknown algorithm %s.", algorithm); - return NULL; - } -} - -char *compute_and_encode_signature(const grpc_auth_json_key *json_key, - const char *signature_algorithm, - const char *to_sign) { - const EVP_MD *md = openssl_digest_from_algorithm(signature_algorithm); - EVP_MD_CTX *md_ctx = NULL; - EVP_PKEY *key = EVP_PKEY_new(); - size_t sig_len = 0; - unsigned char *sig = NULL; - char *result = NULL; - if (md == NULL) return NULL; - md_ctx = EVP_MD_CTX_create(); - if (md_ctx == NULL) { - gpr_log(GPR_ERROR, "Could not create MD_CTX"); - goto end; - } - EVP_PKEY_set1_RSA(key, json_key->private_key); - if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, key) != 1) { - gpr_log(GPR_ERROR, "DigestInit failed."); - goto end; - } - if (EVP_DigestSignUpdate(md_ctx, to_sign, strlen(to_sign)) != 1) { - gpr_log(GPR_ERROR, "DigestUpdate failed."); - goto end; - } - if (EVP_DigestSignFinal(md_ctx, NULL, &sig_len) != 1) { - gpr_log(GPR_ERROR, "DigestFinal (get signature length) failed."); - goto end; - } - sig = gpr_malloc(sig_len); - if (EVP_DigestSignFinal(md_ctx, sig, &sig_len) != 1) { - gpr_log(GPR_ERROR, "DigestFinal (signature compute) failed."); - goto end; - } - result = grpc_base64_encode(sig, sig_len, 1, 0); - -end: - if (key != NULL) EVP_PKEY_free(key); - if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); - if (sig != NULL) gpr_free(sig); - return result; -} - -char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key, - const char *audience, - gpr_timespec token_lifetime, const char *scope) { - if (g_jwt_encode_and_sign_override != NULL) { - return g_jwt_encode_and_sign_override(json_key, audience, token_lifetime, - scope); - } else { - const char *sig_algo = GRPC_JWT_RSA_SHA256_ALGORITHM; - char *to_sign = dot_concat_and_free_strings( - encoded_jwt_header(json_key->private_key_id, sig_algo), - encoded_jwt_claim(json_key, audience, token_lifetime, scope)); - char *sig = compute_and_encode_signature(json_key, sig_algo, to_sign); - if (sig == NULL) { - gpr_free(to_sign); - return NULL; - } - return dot_concat_and_free_strings(to_sign, sig); - } -} - -void grpc_jwt_encode_and_sign_set_override( - grpc_jwt_encode_and_sign_override func) { - g_jwt_encode_and_sign_override = func; -} - -/* --- grpc_auth_refresh_token --- */ - -int grpc_auth_refresh_token_is_valid( - const grpc_auth_refresh_token *refresh_token) { - return (refresh_token != NULL) && - strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID); -} - -grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json( - const grpc_json *json) { - grpc_auth_refresh_token result; - const char *prop_value; - int success = 0; - - memset(&result, 0, sizeof(grpc_auth_refresh_token)); - result.type = GRPC_AUTH_JSON_TYPE_INVALID; - if (json == NULL) { - gpr_log(GPR_ERROR, "Invalid json."); - goto end; - } - - prop_value = json_get_string_property(json, "type"); - if (prop_value == NULL || - strcmp(prop_value, GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER)) { - goto end; - } - result.type = GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER; - - if (!set_json_key_string_property(json, "client_secret", - &result.client_secret) || - !set_json_key_string_property(json, "client_id", &result.client_id) || - !set_json_key_string_property(json, "refresh_token", - &result.refresh_token)) { - goto end; - } - success = 1; - -end: - if (!success) grpc_auth_refresh_token_destruct(&result); - return result; -} - -grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( - const char *json_string) { - char *scratchpad = gpr_strdup(json_string); - grpc_json *json = grpc_json_parse_string(scratchpad); - grpc_auth_refresh_token result = - grpc_auth_refresh_token_create_from_json(json); - if (json != NULL) grpc_json_destroy(json); - gpr_free(scratchpad); - return result; -} - -void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token) { - if (refresh_token == NULL) return; - refresh_token->type = GRPC_AUTH_JSON_TYPE_INVALID; - if (refresh_token->client_id != NULL) { - gpr_free(refresh_token->client_id); - refresh_token->client_id = NULL; - } - if (refresh_token->client_secret != NULL) { - gpr_free(refresh_token->client_secret); - refresh_token->client_secret = NULL; - } - if (refresh_token->refresh_token != NULL) { - gpr_free(refresh_token->refresh_token); - refresh_token->refresh_token = NULL; - } -} diff --git a/src/core/lib/security/json_token.h b/src/core/lib/security/json_token.h deleted file mode 100644 index 123fa652fd..0000000000 --- a/src/core/lib/security/json_token.h +++ /dev/null @@ -1,118 +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. - * - */ - -#ifndef GRPC_CORE_LIB_SECURITY_JSON_TOKEN_H -#define GRPC_CORE_LIB_SECURITY_JSON_TOKEN_H - -#include -#include - -#include "src/core/lib/json/json.h" - -/* --- Constants. --- */ - -#define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token" - -#define GRPC_AUTH_JSON_TYPE_INVALID "invalid" -#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account" -#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user" - -/* --- auth_json_key parsing. --- */ - -typedef struct { - const char *type; - char *private_key_id; - char *client_id; - char *client_email; - RSA *private_key; -} grpc_auth_json_key; - -/* Returns 1 if the object is valid, 0 otherwise. */ -int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key); - -/* Creates a json_key object from string. Returns an invalid object if a parsing - error has been encountered. */ -grpc_auth_json_key grpc_auth_json_key_create_from_string( - const char *json_string); - -/* Creates a json_key object from parsed json. Returns an invalid object if a - parsing error has been encountered. */ -grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json); - -/* Destructs the object. */ -void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key); - -/* --- json token encoding and signing. --- */ - -/* Caller is responsible for calling gpr_free on the returned value. May return - NULL on invalid input. The scope parameter may be NULL. */ -char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key, - const char *audience, - gpr_timespec token_lifetime, const char *scope); - -/* Override encode_and_sign function for testing. */ -typedef char *(*grpc_jwt_encode_and_sign_override)( - const grpc_auth_json_key *json_key, const char *audience, - gpr_timespec token_lifetime, const char *scope); - -/* Set a custom encode_and_sign override for testing. */ -void grpc_jwt_encode_and_sign_set_override( - grpc_jwt_encode_and_sign_override func); - -/* --- auth_refresh_token parsing. --- */ - -typedef struct { - const char *type; - char *client_id; - char *client_secret; - char *refresh_token; -} grpc_auth_refresh_token; - -/* Returns 1 if the object is valid, 0 otherwise. */ -int grpc_auth_refresh_token_is_valid( - const grpc_auth_refresh_token *refresh_token); - -/* Creates a refresh token object from string. Returns an invalid object if a - parsing error has been encountered. */ -grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( - const char *json_string); - -/* Creates a refresh token object from parsed json. Returns an invalid object if - a parsing error has been encountered. */ -grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json( - const grpc_json *json); - -/* Destructs the object. */ -void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token); - -#endif /* GRPC_CORE_LIB_SECURITY_JSON_TOKEN_H */ diff --git a/src/core/lib/security/jwt_verifier.c b/src/core/lib/security/jwt_verifier.c deleted file mode 100644 index 0e012294de..0000000000 --- a/src/core/lib/security/jwt_verifier.c +++ /dev/null @@ -1,843 +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 "src/core/lib/security/jwt_verifier.h" - -#include -#include - -#include "src/core/lib/http/httpcli.h" -#include "src/core/lib/security/b64.h" -#include "src/core/lib/tsi/ssl_types.h" - -#include -#include -#include -#include -#include - -/* --- Utils. --- */ - -const char *grpc_jwt_verifier_status_to_string( - grpc_jwt_verifier_status status) { - switch (status) { - case GRPC_JWT_VERIFIER_OK: - return "OK"; - case GRPC_JWT_VERIFIER_BAD_SIGNATURE: - return "BAD_SIGNATURE"; - case GRPC_JWT_VERIFIER_BAD_FORMAT: - return "BAD_FORMAT"; - case GRPC_JWT_VERIFIER_BAD_AUDIENCE: - return "BAD_AUDIENCE"; - case GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR: - return "KEY_RETRIEVAL_ERROR"; - case GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE: - return "TIME_CONSTRAINT_FAILURE"; - case GRPC_JWT_VERIFIER_GENERIC_ERROR: - return "GENERIC_ERROR"; - default: - return "UNKNOWN"; - } -} - -static const EVP_MD *evp_md_from_alg(const char *alg) { - if (strcmp(alg, "RS256") == 0) { - return EVP_sha256(); - } else if (strcmp(alg, "RS384") == 0) { - return EVP_sha384(); - } else if (strcmp(alg, "RS512") == 0) { - return EVP_sha512(); - } else { - return NULL; - } -} - -static grpc_json *parse_json_part_from_jwt(const char *str, size_t len, - gpr_slice *buffer) { - grpc_json *json; - - *buffer = grpc_base64_decode_with_len(str, len, 1); - if (GPR_SLICE_IS_EMPTY(*buffer)) { - gpr_log(GPR_ERROR, "Invalid base64."); - return NULL; - } - json = grpc_json_parse_string_with_len((char *)GPR_SLICE_START_PTR(*buffer), - GPR_SLICE_LENGTH(*buffer)); - if (json == NULL) { - gpr_slice_unref(*buffer); - gpr_log(GPR_ERROR, "JSON parsing error."); - } - return json; -} - -static const char *validate_string_field(const grpc_json *json, - const char *key) { - if (json->type != GRPC_JSON_STRING) { - gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value); - return NULL; - } - return json->value; -} - -static gpr_timespec validate_time_field(const grpc_json *json, - const char *key) { - gpr_timespec result = gpr_time_0(GPR_CLOCK_REALTIME); - if (json->type != GRPC_JSON_NUMBER) { - gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value); - return result; - } - result.tv_sec = strtol(json->value, NULL, 10); - return result; -} - -/* --- JOSE header. see http://tools.ietf.org/html/rfc7515#section-4 --- */ - -typedef struct { - const char *alg; - const char *kid; - const char *typ; - /* TODO(jboeuf): Add others as needed (jku, jwk, x5u, x5c and so on...). */ - gpr_slice buffer; -} jose_header; - -static void jose_header_destroy(jose_header *h) { - gpr_slice_unref(h->buffer); - gpr_free(h); -} - -/* Takes ownership of json and buffer. */ -static jose_header *jose_header_from_json(grpc_json *json, gpr_slice buffer) { - grpc_json *cur; - jose_header *h = gpr_malloc(sizeof(jose_header)); - memset(h, 0, sizeof(jose_header)); - h->buffer = buffer; - for (cur = json->child; cur != NULL; cur = cur->next) { - if (strcmp(cur->key, "alg") == 0) { - /* We only support RSA-1.5 signatures for now. - Beware of this if we add HMAC support: - https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ - */ - if (cur->type != GRPC_JSON_STRING || strncmp(cur->value, "RS", 2) || - evp_md_from_alg(cur->value) == NULL) { - gpr_log(GPR_ERROR, "Invalid alg field [%s]", cur->value); - goto error; - } - h->alg = cur->value; - } else if (strcmp(cur->key, "typ") == 0) { - h->typ = validate_string_field(cur, "typ"); - if (h->typ == NULL) goto error; - } else if (strcmp(cur->key, "kid") == 0) { - h->kid = validate_string_field(cur, "kid"); - if (h->kid == NULL) goto error; - } - } - if (h->alg == NULL) { - gpr_log(GPR_ERROR, "Missing alg field."); - goto error; - } - grpc_json_destroy(json); - h->buffer = buffer; - return h; - -error: - grpc_json_destroy(json); - jose_header_destroy(h); - return NULL; -} - -/* --- JWT claims. see http://tools.ietf.org/html/rfc7519#section-4.1 */ - -struct grpc_jwt_claims { - /* Well known properties already parsed. */ - const char *sub; - const char *iss; - const char *aud; - const char *jti; - gpr_timespec iat; - gpr_timespec exp; - gpr_timespec nbf; - - grpc_json *json; - gpr_slice buffer; -}; - -void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) { - grpc_json_destroy(claims->json); - gpr_slice_unref(claims->buffer); - gpr_free(claims); -} - -const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims) { - if (claims == NULL) return NULL; - return claims->json; -} - -const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims) { - if (claims == NULL) return NULL; - return claims->sub; -} - -const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims) { - if (claims == NULL) return NULL; - return claims->iss; -} - -const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims) { - if (claims == NULL) return NULL; - return claims->jti; -} - -const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims) { - if (claims == NULL) return NULL; - return claims->aud; -} - -gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims) { - if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME); - return claims->iat; -} - -gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims) { - if (claims == NULL) return gpr_inf_future(GPR_CLOCK_REALTIME); - return claims->exp; -} - -gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims) { - if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME); - return claims->nbf; -} - -/* Takes ownership of json and buffer even in case of failure. */ -grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer) { - grpc_json *cur; - grpc_jwt_claims *claims = gpr_malloc(sizeof(grpc_jwt_claims)); - memset(claims, 0, sizeof(grpc_jwt_claims)); - claims->json = json; - claims->buffer = buffer; - claims->iat = gpr_inf_past(GPR_CLOCK_REALTIME); - claims->nbf = gpr_inf_past(GPR_CLOCK_REALTIME); - claims->exp = gpr_inf_future(GPR_CLOCK_REALTIME); - - /* Per the spec, all fields are optional. */ - for (cur = json->child; cur != NULL; cur = cur->next) { - if (strcmp(cur->key, "sub") == 0) { - claims->sub = validate_string_field(cur, "sub"); - if (claims->sub == NULL) goto error; - } else if (strcmp(cur->key, "iss") == 0) { - claims->iss = validate_string_field(cur, "iss"); - if (claims->iss == NULL) goto error; - } else if (strcmp(cur->key, "aud") == 0) { - claims->aud = validate_string_field(cur, "aud"); - if (claims->aud == NULL) goto error; - } else if (strcmp(cur->key, "jti") == 0) { - claims->jti = validate_string_field(cur, "jti"); - if (claims->jti == NULL) goto error; - } else if (strcmp(cur->key, "iat") == 0) { - claims->iat = validate_time_field(cur, "iat"); - if (gpr_time_cmp(claims->iat, gpr_time_0(GPR_CLOCK_REALTIME)) == 0) - goto error; - } else if (strcmp(cur->key, "exp") == 0) { - claims->exp = validate_time_field(cur, "exp"); - if (gpr_time_cmp(claims->exp, gpr_time_0(GPR_CLOCK_REALTIME)) == 0) - goto error; - } else if (strcmp(cur->key, "nbf") == 0) { - claims->nbf = validate_time_field(cur, "nbf"); - if (gpr_time_cmp(claims->nbf, gpr_time_0(GPR_CLOCK_REALTIME)) == 0) - goto error; - } - } - return claims; - -error: - grpc_jwt_claims_destroy(claims); - return NULL; -} - -grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims, - const char *audience) { - gpr_timespec skewed_now; - int audience_ok; - - GPR_ASSERT(claims != NULL); - - skewed_now = - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew); - if (gpr_time_cmp(skewed_now, claims->nbf) < 0) { - gpr_log(GPR_ERROR, "JWT is not valid yet."); - return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE; - } - skewed_now = - gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew); - if (gpr_time_cmp(skewed_now, claims->exp) > 0) { - gpr_log(GPR_ERROR, "JWT is expired."); - return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE; - } - - if (audience == NULL) { - audience_ok = claims->aud == NULL; - } else { - audience_ok = claims->aud != NULL && strcmp(audience, claims->aud) == 0; - } - if (!audience_ok) { - gpr_log(GPR_ERROR, "Audience mismatch: expected %s and found %s.", - audience == NULL ? "NULL" : audience, - claims->aud == NULL ? "NULL" : claims->aud); - return GRPC_JWT_VERIFIER_BAD_AUDIENCE; - } - return GRPC_JWT_VERIFIER_OK; -} - -/* --- verifier_cb_ctx object. --- */ - -typedef struct { - grpc_jwt_verifier *verifier; - grpc_pollset *pollset; - jose_header *header; - grpc_jwt_claims *claims; - char *audience; - gpr_slice signature; - gpr_slice signed_data; - void *user_data; - grpc_jwt_verification_done_cb user_cb; -} verifier_cb_ctx; - -/* Takes ownership of the header, claims and signature. */ -static verifier_cb_ctx *verifier_cb_ctx_create( - grpc_jwt_verifier *verifier, grpc_pollset *pollset, jose_header *header, - grpc_jwt_claims *claims, const char *audience, gpr_slice signature, - const char *signed_jwt, size_t signed_jwt_len, void *user_data, - grpc_jwt_verification_done_cb cb) { - verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx)); - memset(ctx, 0, sizeof(verifier_cb_ctx)); - ctx->verifier = verifier; - ctx->pollset = pollset; - ctx->header = header; - ctx->audience = gpr_strdup(audience); - ctx->claims = claims; - ctx->signature = signature; - ctx->signed_data = gpr_slice_from_copied_buffer(signed_jwt, signed_jwt_len); - ctx->user_data = user_data; - ctx->user_cb = cb; - return ctx; -} - -void verifier_cb_ctx_destroy(verifier_cb_ctx *ctx) { - if (ctx->audience != NULL) gpr_free(ctx->audience); - if (ctx->claims != NULL) grpc_jwt_claims_destroy(ctx->claims); - gpr_slice_unref(ctx->signature); - gpr_slice_unref(ctx->signed_data); - jose_header_destroy(ctx->header); - /* TODO: see what to do with claims... */ - gpr_free(ctx); -} - -/* --- grpc_jwt_verifier object. --- */ - -/* Clock skew defaults to one minute. */ -gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0, GPR_TIMESPAN}; - -/* Max delay defaults to one minute. */ -gpr_timespec grpc_jwt_verifier_max_delay = {60, 0, GPR_TIMESPAN}; - -typedef struct { - char *email_domain; - char *key_url_prefix; -} email_key_mapping; - -struct grpc_jwt_verifier { - email_key_mapping *mappings; - size_t num_mappings; /* Should be very few, linear search ok. */ - size_t allocated_mappings; - grpc_httpcli_context http_ctx; -}; - -static grpc_json *json_from_http(const grpc_httpcli_response *response) { - grpc_json *json = NULL; - - if (response == NULL) { - gpr_log(GPR_ERROR, "HTTP response is NULL."); - return NULL; - } - if (response->status != 200) { - gpr_log(GPR_ERROR, "Call to http server failed with error %d.", - response->status); - return NULL; - } - - json = grpc_json_parse_string_with_len(response->body, response->body_length); - if (json == NULL) { - gpr_log(GPR_ERROR, "Invalid JSON found in response."); - } - return json; -} - -static const grpc_json *find_property_by_name(const grpc_json *json, - const char *name) { - const grpc_json *cur; - for (cur = json->child; cur != NULL; cur = cur->next) { - if (strcmp(cur->key, name) == 0) return cur; - } - return NULL; -} - -static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) { - X509 *x509 = NULL; - EVP_PKEY *result = NULL; - BIO *bio = BIO_new(BIO_s_mem()); - size_t len = strlen(x509_str); - GPR_ASSERT(len < INT_MAX); - BIO_write(bio, x509_str, (int)len); - x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); - if (x509 == NULL) { - gpr_log(GPR_ERROR, "Unable to parse x509 cert."); - goto end; - } - result = X509_get_pubkey(x509); - if (result == NULL) { - gpr_log(GPR_ERROR, "Cannot find public key in X509 cert."); - } - -end: - BIO_free(bio); - if (x509 != NULL) X509_free(x509); - return result; -} - -static BIGNUM *bignum_from_base64(const char *b64) { - BIGNUM *result = NULL; - gpr_slice bin; - - if (b64 == NULL) return NULL; - bin = grpc_base64_decode(b64, 1); - if (GPR_SLICE_IS_EMPTY(bin)) { - gpr_log(GPR_ERROR, "Invalid base64 for big num."); - return NULL; - } - result = BN_bin2bn(GPR_SLICE_START_PTR(bin), - TSI_SIZE_AS_SIZE(GPR_SLICE_LENGTH(bin)), NULL); - gpr_slice_unref(bin); - return result; -} - -static EVP_PKEY *pkey_from_jwk(const grpc_json *json, const char *kty) { - const grpc_json *key_prop; - RSA *rsa = NULL; - EVP_PKEY *result = NULL; - - GPR_ASSERT(kty != NULL && json != NULL); - if (strcmp(kty, "RSA") != 0) { - gpr_log(GPR_ERROR, "Unsupported key type %s.", kty); - goto end; - } - rsa = RSA_new(); - if (rsa == NULL) { - gpr_log(GPR_ERROR, "Could not create rsa key."); - goto end; - } - for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) { - if (strcmp(key_prop->key, "n") == 0) { - rsa->n = bignum_from_base64(validate_string_field(key_prop, "n")); - if (rsa->n == NULL) goto end; - } else if (strcmp(key_prop->key, "e") == 0) { - rsa->e = bignum_from_base64(validate_string_field(key_prop, "e")); - if (rsa->e == NULL) goto end; - } - } - if (rsa->e == NULL || rsa->n == NULL) { - gpr_log(GPR_ERROR, "Missing RSA public key field."); - goto end; - } - result = EVP_PKEY_new(); - EVP_PKEY_set1_RSA(result, rsa); /* uprefs rsa. */ - -end: - if (rsa != NULL) RSA_free(rsa); - return result; -} - -static EVP_PKEY *find_verification_key(const grpc_json *json, - const char *header_alg, - const char *header_kid) { - const grpc_json *jkey; - const grpc_json *jwk_keys; - /* Try to parse the json as a JWK set: - https://tools.ietf.org/html/rfc7517#section-5. */ - jwk_keys = find_property_by_name(json, "keys"); - if (jwk_keys == NULL) { - /* Use the google proprietary format which is: - { : , : , ... } */ - const grpc_json *cur = find_property_by_name(json, header_kid); - if (cur == NULL) return NULL; - return extract_pkey_from_x509(cur->value); - } - - if (jwk_keys->type != GRPC_JSON_ARRAY) { - gpr_log(GPR_ERROR, - "Unexpected value type of keys property in jwks key set."); - return NULL; - } - /* Key format is specified in: - https://tools.ietf.org/html/rfc7518#section-6. */ - for (jkey = jwk_keys->child; jkey != NULL; jkey = jkey->next) { - grpc_json *key_prop; - const char *alg = NULL; - const char *kid = NULL; - const char *kty = NULL; - - if (jkey->type != GRPC_JSON_OBJECT) continue; - for (key_prop = jkey->child; key_prop != NULL; key_prop = key_prop->next) { - if (strcmp(key_prop->key, "alg") == 0 && - key_prop->type == GRPC_JSON_STRING) { - alg = key_prop->value; - } else if (strcmp(key_prop->key, "kid") == 0 && - key_prop->type == GRPC_JSON_STRING) { - kid = key_prop->value; - } else if (strcmp(key_prop->key, "kty") == 0 && - key_prop->type == GRPC_JSON_STRING) { - kty = key_prop->value; - } - } - if (alg != NULL && kid != NULL && kty != NULL && - strcmp(kid, header_kid) == 0 && strcmp(alg, header_alg) == 0) { - return pkey_from_jwk(jkey, kty); - } - } - gpr_log(GPR_ERROR, - "Could not find matching key in key set for kid=%s and alg=%s", - header_kid, header_alg); - return NULL; -} - -static int verify_jwt_signature(EVP_PKEY *key, const char *alg, - gpr_slice signature, gpr_slice signed_data) { - EVP_MD_CTX *md_ctx = EVP_MD_CTX_create(); - const EVP_MD *md = evp_md_from_alg(alg); - int result = 0; - - GPR_ASSERT(md != NULL); /* Checked before. */ - if (md_ctx == NULL) { - gpr_log(GPR_ERROR, "Could not create EVP_MD_CTX."); - goto end; - } - if (EVP_DigestVerifyInit(md_ctx, NULL, md, NULL, key) != 1) { - gpr_log(GPR_ERROR, "EVP_DigestVerifyInit failed."); - goto end; - } - if (EVP_DigestVerifyUpdate(md_ctx, GPR_SLICE_START_PTR(signed_data), - GPR_SLICE_LENGTH(signed_data)) != 1) { - gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed."); - goto end; - } - if (EVP_DigestVerifyFinal(md_ctx, GPR_SLICE_START_PTR(signature), - GPR_SLICE_LENGTH(signature)) != 1) { - gpr_log(GPR_ERROR, "JWT signature verification failed."); - goto end; - } - result = 1; - -end: - if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); - return result; -} - -static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data, - const grpc_httpcli_response *response) { - grpc_json *json = json_from_http(response); - verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data; - EVP_PKEY *verification_key = NULL; - grpc_jwt_verifier_status status = GRPC_JWT_VERIFIER_GENERIC_ERROR; - grpc_jwt_claims *claims = NULL; - - if (json == NULL) { - status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR; - goto end; - } - verification_key = - find_verification_key(json, ctx->header->alg, ctx->header->kid); - if (verification_key == NULL) { - gpr_log(GPR_ERROR, "Could not find verification key with kid %s.", - ctx->header->kid); - status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR; - goto end; - } - - if (!verify_jwt_signature(verification_key, ctx->header->alg, ctx->signature, - ctx->signed_data)) { - status = GRPC_JWT_VERIFIER_BAD_SIGNATURE; - goto end; - } - - status = grpc_jwt_claims_check(ctx->claims, ctx->audience); - if (status == GRPC_JWT_VERIFIER_OK) { - /* Pass ownership. */ - claims = ctx->claims; - ctx->claims = NULL; - } - -end: - if (json != NULL) grpc_json_destroy(json); - if (verification_key != NULL) EVP_PKEY_free(verification_key); - ctx->user_cb(ctx->user_data, status, claims); - verifier_cb_ctx_destroy(ctx); -} - -static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data, - const grpc_httpcli_response *response) { - const grpc_json *cur; - grpc_json *json = json_from_http(response); - verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data; - grpc_httpcli_request req; - const char *jwks_uri; - - /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time. */ - if (json == NULL) goto error; - cur = find_property_by_name(json, "jwks_uri"); - if (cur == NULL) { - gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config."); - goto error; - } - jwks_uri = validate_string_field(cur, "jwks_uri"); - if (jwks_uri == NULL) goto error; - if (strstr(jwks_uri, "https://") != jwks_uri) { - gpr_log(GPR_ERROR, "Invalid non https jwks_uri: %s.", jwks_uri); - goto error; - } - jwks_uri += 8; - req.handshaker = &grpc_httpcli_ssl; - req.host = gpr_strdup(jwks_uri); - req.http.path = strchr(jwks_uri, '/'); - if (req.http.path == NULL) { - req.http.path = ""; - } else { - *(req.host + (req.http.path - jwks_uri)) = '\0'; - } - grpc_httpcli_get( - exec_ctx, &ctx->verifier->http_ctx, ctx->pollset, &req, - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay), - on_keys_retrieved, ctx); - grpc_json_destroy(json); - gpr_free(req.host); - return; - -error: - if (json != NULL) grpc_json_destroy(json); - ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL); - verifier_cb_ctx_destroy(ctx); -} - -static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v, - const char *email_domain) { - size_t i; - if (v->mappings == NULL) return NULL; - for (i = 0; i < v->num_mappings; i++) { - if (strcmp(email_domain, v->mappings[i].email_domain) == 0) { - return &v->mappings[i]; - } - } - return NULL; -} - -static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain, - const char *key_url_prefix) { - email_key_mapping *mapping = verifier_get_mapping(v, email_domain); - GPR_ASSERT(v->num_mappings < v->allocated_mappings); - if (mapping != NULL) { - gpr_free(mapping->key_url_prefix); - mapping->key_url_prefix = gpr_strdup(key_url_prefix); - return; - } - v->mappings[v->num_mappings].email_domain = gpr_strdup(email_domain); - v->mappings[v->num_mappings].key_url_prefix = gpr_strdup(key_url_prefix); - v->num_mappings++; - GPR_ASSERT(v->num_mappings <= v->allocated_mappings); -} - -/* Takes ownership of ctx. */ -static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx, - verifier_cb_ctx *ctx) { - const char *at_sign; - grpc_httpcli_response_cb http_cb; - char *path_prefix = NULL; - const char *iss; - grpc_httpcli_request req; - memset(&req, 0, sizeof(grpc_httpcli_request)); - req.handshaker = &grpc_httpcli_ssl; - - GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL); - iss = ctx->claims->iss; - if (ctx->header->kid == NULL) { - gpr_log(GPR_ERROR, "Missing kid in jose header."); - goto error; - } - if (iss == NULL) { - gpr_log(GPR_ERROR, "Missing iss in claims."); - goto error; - } - - /* This code relies on: - https://openid.net/specs/openid-connect-discovery-1_0.html - Nobody seems to implement the account/email/webfinger part 2. of the spec - so we will rely instead on email/url mappings if we detect such an issuer. - Part 4, on the other hand is implemented by both google and salesforce. */ - - /* Very non-sophisticated way to detect an email address. Should be good - enough for now... */ - at_sign = strchr(iss, '@'); - if (at_sign != NULL) { - email_key_mapping *mapping; - const char *email_domain = at_sign + 1; - GPR_ASSERT(ctx->verifier != NULL); - mapping = verifier_get_mapping(ctx->verifier, email_domain); - if (mapping == NULL) { - gpr_log(GPR_ERROR, "Missing mapping for issuer email."); - goto error; - } - req.host = gpr_strdup(mapping->key_url_prefix); - path_prefix = strchr(req.host, '/'); - if (path_prefix == NULL) { - gpr_asprintf(&req.http.path, "/%s", iss); - } else { - *(path_prefix++) = '\0'; - gpr_asprintf(&req.http.path, "/%s/%s", path_prefix, iss); - } - http_cb = on_keys_retrieved; - } else { - req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss); - path_prefix = strchr(req.host, '/'); - if (path_prefix == NULL) { - req.http.path = gpr_strdup(GRPC_OPENID_CONFIG_URL_SUFFIX); - } else { - *(path_prefix++) = 0; - gpr_asprintf(&req.http.path, "/%s%s", path_prefix, - GRPC_OPENID_CONFIG_URL_SUFFIX); - } - http_cb = on_openid_config_retrieved; - } - - grpc_httpcli_get( - exec_ctx, &ctx->verifier->http_ctx, ctx->pollset, &req, - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay), - http_cb, ctx); - gpr_free(req.host); - gpr_free(req.http.path); - return; - -error: - ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL); - verifier_cb_ctx_destroy(ctx); -} - -void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, - grpc_jwt_verifier *verifier, - grpc_pollset *pollset, const char *jwt, - const char *audience, - grpc_jwt_verification_done_cb cb, - void *user_data) { - const char *dot = NULL; - grpc_json *json; - jose_header *header = NULL; - grpc_jwt_claims *claims = NULL; - gpr_slice header_buffer; - gpr_slice claims_buffer; - gpr_slice signature; - size_t signed_jwt_len; - const char *cur = jwt; - - GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL); - dot = strchr(cur, '.'); - if (dot == NULL) goto error; - json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &header_buffer); - if (json == NULL) goto error; - header = jose_header_from_json(json, header_buffer); - if (header == NULL) goto error; - - cur = dot + 1; - dot = strchr(cur, '.'); - if (dot == NULL) goto error; - json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer); - if (json == NULL) goto error; - claims = grpc_jwt_claims_from_json(json, claims_buffer); - if (claims == NULL) goto error; - - signed_jwt_len = (size_t)(dot - jwt); - cur = dot + 1; - signature = grpc_base64_decode(cur, 1); - if (GPR_SLICE_IS_EMPTY(signature)) goto error; - retrieve_key_and_verify( - exec_ctx, - verifier_cb_ctx_create(verifier, pollset, header, claims, audience, - signature, jwt, signed_jwt_len, user_data, cb)); - return; - -error: - if (header != NULL) jose_header_destroy(header); - if (claims != NULL) grpc_jwt_claims_destroy(claims); - cb(user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL); -} - -grpc_jwt_verifier *grpc_jwt_verifier_create( - const grpc_jwt_verifier_email_domain_key_url_mapping *mappings, - size_t num_mappings) { - grpc_jwt_verifier *v = gpr_malloc(sizeof(grpc_jwt_verifier)); - memset(v, 0, sizeof(grpc_jwt_verifier)); - grpc_httpcli_context_init(&v->http_ctx); - - /* We know at least of one mapping. */ - v->allocated_mappings = 1 + num_mappings; - v->mappings = gpr_malloc(v->allocated_mappings * sizeof(email_key_mapping)); - verifier_put_mapping(v, GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN, - GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX); - /* User-Provided mappings. */ - if (mappings != NULL) { - size_t i; - for (i = 0; i < num_mappings; i++) { - verifier_put_mapping(v, mappings[i].email_domain, - mappings[i].key_url_prefix); - } - } - return v; -} - -void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) { - size_t i; - if (v == NULL) return; - grpc_httpcli_context_destroy(&v->http_ctx); - if (v->mappings != NULL) { - for (i = 0; i < v->num_mappings; i++) { - gpr_free(v->mappings[i].email_domain); - gpr_free(v->mappings[i].key_url_prefix); - } - gpr_free(v->mappings); - } - gpr_free(v); -} diff --git a/src/core/lib/security/jwt_verifier.h b/src/core/lib/security/jwt_verifier.h deleted file mode 100644 index 98a4f6b116..0000000000 --- a/src/core/lib/security/jwt_verifier.h +++ /dev/null @@ -1,136 +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. - * - */ - -#ifndef GRPC_CORE_LIB_SECURITY_JWT_VERIFIER_H -#define GRPC_CORE_LIB_SECURITY_JWT_VERIFIER_H - -#include "src/core/lib/iomgr/pollset.h" -#include "src/core/lib/json/json.h" - -#include -#include - -/* --- Constants. --- */ - -#define GRPC_OPENID_CONFIG_URL_SUFFIX "/.well-known/openid-configuration" -#define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN \ - "developer.gserviceaccount.com" -#define GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX \ - "www.googleapis.com/robot/v1/metadata/x509" - -/* --- grpc_jwt_verifier_status. --- */ - -typedef enum { - GRPC_JWT_VERIFIER_OK = 0, - GRPC_JWT_VERIFIER_BAD_SIGNATURE, - GRPC_JWT_VERIFIER_BAD_FORMAT, - GRPC_JWT_VERIFIER_BAD_AUDIENCE, - GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, - GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE, - GRPC_JWT_VERIFIER_GENERIC_ERROR -} grpc_jwt_verifier_status; - -const char *grpc_jwt_verifier_status_to_string(grpc_jwt_verifier_status status); - -/* --- grpc_jwt_claims. --- */ - -typedef struct grpc_jwt_claims grpc_jwt_claims; - -void grpc_jwt_claims_destroy(grpc_jwt_claims *claims); - -/* Returns the whole JSON tree of the claims. */ -const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims); - -/* Access to registered claims in https://tools.ietf.org/html/rfc7519#page-9 */ -const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims); -const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims); -const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims); -const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims); -gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims); -gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims); -gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims); - -/* --- grpc_jwt_verifier. --- */ - -typedef struct grpc_jwt_verifier grpc_jwt_verifier; - -typedef struct { - /* The email domain is the part after the @ sign. */ - const char *email_domain; - - /* The key url prefix will be used to get the public key from the issuer: - https:/// - Therefore the key_url_prefix must NOT contain https://. */ - const char *key_url_prefix; -} grpc_jwt_verifier_email_domain_key_url_mapping; - -/* Globals to control the verifier. Not thread-safe. */ -extern gpr_timespec grpc_jwt_verifier_clock_skew; -extern gpr_timespec grpc_jwt_verifier_max_delay; - -/* The verifier can be created with some custom mappings to help with key - discovery in the case where the issuer is an email address. - mappings can be NULL in which case num_mappings MUST be 0. - A verifier object has one built-in mapping (unless overridden): - GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN -> - GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX.*/ -grpc_jwt_verifier *grpc_jwt_verifier_create( - const grpc_jwt_verifier_email_domain_key_url_mapping *mappings, - size_t num_mappings); - -/*The verifier must not be destroyed if there are still outstanding callbacks.*/ -void grpc_jwt_verifier_destroy(grpc_jwt_verifier *verifier); - -/* User provided callback that will be called when the verification of the JWT - is done (maybe in another thread). - It is the responsibility of the callee to call grpc_jwt_claims_destroy on - the claims. */ -typedef void (*grpc_jwt_verification_done_cb)(void *user_data, - grpc_jwt_verifier_status status, - grpc_jwt_claims *claims); - -/* Verifies for the JWT for the given expected audience. */ -void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, - grpc_jwt_verifier *verifier, - grpc_pollset *pollset, const char *jwt, - const char *audience, - grpc_jwt_verification_done_cb cb, - void *user_data); - -/* --- TESTING ONLY exposed functions. --- */ - -grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer); -grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims, - const char *audience); - -#endif /* GRPC_CORE_LIB_SECURITY_JWT_VERIFIER_H */ diff --git a/src/core/lib/security/secure_endpoint.c b/src/core/lib/security/secure_endpoint.c deleted file mode 100644 index 27b0e98910..0000000000 --- a/src/core/lib/security/secure_endpoint.c +++ /dev/null @@ -1,384 +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 "src/core/lib/security/secure_endpoint.h" -#include -#include -#include -#include -#include -#include "src/core/lib/debug/trace.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/tsi/transport_security_interface.h" - -#define STAGING_BUFFER_SIZE 8192 - -typedef struct { - grpc_endpoint base; - grpc_endpoint *wrapped_ep; - struct tsi_frame_protector *protector; - gpr_mu protector_mu; - /* saved upper level callbacks and user_data. */ - grpc_closure *read_cb; - grpc_closure *write_cb; - grpc_closure on_read; - gpr_slice_buffer *read_buffer; - gpr_slice_buffer source_buffer; - /* saved handshaker leftover data to unprotect. */ - gpr_slice_buffer leftover_bytes; - /* buffers for read and write */ - gpr_slice read_staging_buffer; - - gpr_slice write_staging_buffer; - gpr_slice_buffer output_buffer; - - gpr_refcount ref; -} secure_endpoint; - -int grpc_trace_secure_endpoint = 0; - -static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) { - secure_endpoint *ep = secure_ep; - grpc_endpoint_destroy(exec_ctx, ep->wrapped_ep); - tsi_frame_protector_destroy(ep->protector); - gpr_slice_buffer_destroy(&ep->leftover_bytes); - gpr_slice_unref(ep->read_staging_buffer); - gpr_slice_unref(ep->write_staging_buffer); - gpr_slice_buffer_destroy(&ep->output_buffer); - gpr_slice_buffer_destroy(&ep->source_buffer); - gpr_mu_destroy(&ep->protector_mu); - gpr_free(ep); -} - -/*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/ -#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG -#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \ - secure_endpoint_unref((exec_ctx), (ep), (reason), __FILE__, __LINE__) -#define SECURE_ENDPOINT_REF(ep, reason) \ - secure_endpoint_ref((ep), (reason), __FILE__, __LINE__) -static void secure_endpoint_unref(secure_endpoint *ep, - grpc_closure_list *closure_list, - const char *reason, const char *file, - int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d", - ep, reason, ep->ref.count, ep->ref.count - 1); - if (gpr_unref(&ep->ref)) { - destroy(exec_ctx, ep); - } -} - -static void secure_endpoint_ref(secure_endpoint *ep, const char *reason, - const char *file, int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %d -> %d", - ep, reason, ep->ref.count, ep->ref.count + 1); - gpr_ref(&ep->ref); -} -#else -#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \ - secure_endpoint_unref((exec_ctx), (ep)) -#define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep)) -static void secure_endpoint_unref(grpc_exec_ctx *exec_ctx, - secure_endpoint *ep) { - if (gpr_unref(&ep->ref)) { - destroy(exec_ctx, ep); - } -} - -static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); } -#endif - -static void flush_read_staging_buffer(secure_endpoint *ep, uint8_t **cur, - uint8_t **end) { - gpr_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer); - ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); - *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer); - *end = GPR_SLICE_END_PTR(ep->read_staging_buffer); -} - -static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep, - bool success) { - if (grpc_trace_secure_endpoint) { - size_t i; - for (i = 0; i < ep->read_buffer->count; i++) { - char *data = gpr_dump_slice(ep->read_buffer->slices[i], - GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "READ %p: %s", ep, data); - gpr_free(data); - } - } - ep->read_buffer = NULL; - grpc_exec_ctx_enqueue(exec_ctx, ep->read_cb, success, NULL); - SECURE_ENDPOINT_UNREF(exec_ctx, ep, "read"); -} - -static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success) { - unsigned i; - uint8_t keep_looping = 0; - tsi_result result = TSI_OK; - secure_endpoint *ep = (secure_endpoint *)user_data; - uint8_t *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer); - uint8_t *end = GPR_SLICE_END_PTR(ep->read_staging_buffer); - - if (!success) { - gpr_slice_buffer_reset_and_unref(ep->read_buffer); - call_read_cb(exec_ctx, ep, 0); - return; - } - - /* TODO(yangg) check error, maybe bail out early */ - for (i = 0; i < ep->source_buffer.count; i++) { - gpr_slice encrypted = ep->source_buffer.slices[i]; - uint8_t *message_bytes = GPR_SLICE_START_PTR(encrypted); - size_t message_size = GPR_SLICE_LENGTH(encrypted); - - while (message_size > 0 || keep_looping) { - size_t unprotected_buffer_size_written = (size_t)(end - cur); - size_t processed_message_size = message_size; - gpr_mu_lock(&ep->protector_mu); - result = tsi_frame_protector_unprotect(ep->protector, message_bytes, - &processed_message_size, cur, - &unprotected_buffer_size_written); - gpr_mu_unlock(&ep->protector_mu); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Decryption error: %s", - tsi_result_to_string(result)); - break; - } - message_bytes += processed_message_size; - message_size -= processed_message_size; - cur += unprotected_buffer_size_written; - - if (cur == end) { - flush_read_staging_buffer(ep, &cur, &end); - /* Force to enter the loop again to extract buffered bytes in protector. - The bytes could be buffered because of running out of staging_buffer. - If this happens at the end of all slices, doing another unprotect - avoids leaving data in the protector. */ - keep_looping = 1; - } else if (unprotected_buffer_size_written > 0) { - keep_looping = 1; - } else { - keep_looping = 0; - } - } - if (result != TSI_OK) break; - } - - if (cur != GPR_SLICE_START_PTR(ep->read_staging_buffer)) { - gpr_slice_buffer_add( - ep->read_buffer, - gpr_slice_split_head( - &ep->read_staging_buffer, - (size_t)(cur - GPR_SLICE_START_PTR(ep->read_staging_buffer)))); - } - - /* TODO(yangg) experiment with moving this block after read_cb to see if it - helps latency */ - gpr_slice_buffer_reset_and_unref(&ep->source_buffer); - - if (result != TSI_OK) { - gpr_slice_buffer_reset_and_unref(ep->read_buffer); - call_read_cb(exec_ctx, ep, 0); - return; - } - - call_read_cb(exec_ctx, ep, 1); -} - -static void endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, - gpr_slice_buffer *slices, grpc_closure *cb) { - secure_endpoint *ep = (secure_endpoint *)secure_ep; - ep->read_cb = cb; - ep->read_buffer = slices; - gpr_slice_buffer_reset_and_unref(ep->read_buffer); - - SECURE_ENDPOINT_REF(ep, "read"); - if (ep->leftover_bytes.count) { - gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer); - GPR_ASSERT(ep->leftover_bytes.count == 0); - on_read(exec_ctx, ep, 1); - return; - } - - grpc_endpoint_read(exec_ctx, ep->wrapped_ep, &ep->source_buffer, - &ep->on_read); -} - -static void flush_write_staging_buffer(secure_endpoint *ep, uint8_t **cur, - uint8_t **end) { - gpr_slice_buffer_add(&ep->output_buffer, ep->write_staging_buffer); - ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); - *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer); - *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); -} - -static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, - gpr_slice_buffer *slices, grpc_closure *cb) { - unsigned i; - tsi_result result = TSI_OK; - secure_endpoint *ep = (secure_endpoint *)secure_ep; - uint8_t *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer); - uint8_t *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); - - gpr_slice_buffer_reset_and_unref(&ep->output_buffer); - - if (grpc_trace_secure_endpoint) { - for (i = 0; i < slices->count; i++) { - char *data = - gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); - gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data); - gpr_free(data); - } - } - - for (i = 0; i < slices->count; i++) { - gpr_slice plain = slices->slices[i]; - uint8_t *message_bytes = GPR_SLICE_START_PTR(plain); - size_t message_size = GPR_SLICE_LENGTH(plain); - while (message_size > 0) { - size_t protected_buffer_size_to_send = (size_t)(end - cur); - size_t processed_message_size = message_size; - gpr_mu_lock(&ep->protector_mu); - result = tsi_frame_protector_protect(ep->protector, message_bytes, - &processed_message_size, cur, - &protected_buffer_size_to_send); - gpr_mu_unlock(&ep->protector_mu); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Encryption error: %s", - tsi_result_to_string(result)); - break; - } - message_bytes += processed_message_size; - message_size -= processed_message_size; - cur += protected_buffer_size_to_send; - - if (cur == end) { - flush_write_staging_buffer(ep, &cur, &end); - } - } - if (result != TSI_OK) break; - } - if (result == TSI_OK) { - size_t still_pending_size; - do { - size_t protected_buffer_size_to_send = (size_t)(end - cur); - gpr_mu_lock(&ep->protector_mu); - result = tsi_frame_protector_protect_flush(ep->protector, cur, - &protected_buffer_size_to_send, - &still_pending_size); - gpr_mu_unlock(&ep->protector_mu); - if (result != TSI_OK) break; - cur += protected_buffer_size_to_send; - if (cur == end) { - flush_write_staging_buffer(ep, &cur, &end); - } - } while (still_pending_size > 0); - if (cur != GPR_SLICE_START_PTR(ep->write_staging_buffer)) { - gpr_slice_buffer_add( - &ep->output_buffer, - gpr_slice_split_head( - &ep->write_staging_buffer, - (size_t)(cur - GPR_SLICE_START_PTR(ep->write_staging_buffer)))); - } - } - - if (result != TSI_OK) { - /* TODO(yangg) do different things according to the error type? */ - gpr_slice_buffer_reset_and_unref(&ep->output_buffer); - grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL); - return; - } - - grpc_endpoint_write(exec_ctx, ep->wrapped_ep, &ep->output_buffer, cb); -} - -static void endpoint_shutdown(grpc_exec_ctx *exec_ctx, - grpc_endpoint *secure_ep) { - secure_endpoint *ep = (secure_endpoint *)secure_ep; - grpc_endpoint_shutdown(exec_ctx, ep->wrapped_ep); -} - -static void endpoint_destroy(grpc_exec_ctx *exec_ctx, - grpc_endpoint *secure_ep) { - secure_endpoint *ep = (secure_endpoint *)secure_ep; - SECURE_ENDPOINT_UNREF(exec_ctx, ep, "destroy"); -} - -static void endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx, - grpc_endpoint *secure_ep, - grpc_pollset *pollset) { - secure_endpoint *ep = (secure_endpoint *)secure_ep; - grpc_endpoint_add_to_pollset(exec_ctx, ep->wrapped_ep, pollset); -} - -static void endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx, - grpc_endpoint *secure_ep, - grpc_pollset_set *pollset_set) { - secure_endpoint *ep = (secure_endpoint *)secure_ep; - grpc_endpoint_add_to_pollset_set(exec_ctx, ep->wrapped_ep, pollset_set); -} - -static char *endpoint_get_peer(grpc_endpoint *secure_ep) { - secure_endpoint *ep = (secure_endpoint *)secure_ep; - return grpc_endpoint_get_peer(ep->wrapped_ep); -} - -static const grpc_endpoint_vtable vtable = { - endpoint_read, endpoint_write, - endpoint_add_to_pollset, endpoint_add_to_pollset_set, - endpoint_shutdown, endpoint_destroy, - endpoint_get_peer}; - -grpc_endpoint *grpc_secure_endpoint_create( - struct tsi_frame_protector *protector, grpc_endpoint *transport, - gpr_slice *leftover_slices, size_t leftover_nslices) { - size_t i; - secure_endpoint *ep = (secure_endpoint *)gpr_malloc(sizeof(secure_endpoint)); - ep->base.vtable = &vtable; - ep->wrapped_ep = transport; - ep->protector = protector; - gpr_slice_buffer_init(&ep->leftover_bytes); - for (i = 0; i < leftover_nslices; i++) { - gpr_slice_buffer_add(&ep->leftover_bytes, - gpr_slice_ref(leftover_slices[i])); - } - ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); - ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); - gpr_slice_buffer_init(&ep->output_buffer); - gpr_slice_buffer_init(&ep->source_buffer); - ep->read_buffer = NULL; - grpc_closure_init(&ep->on_read, on_read, ep); - gpr_mu_init(&ep->protector_mu); - gpr_ref_init(&ep->ref, 1); - return &ep->base; -} diff --git a/src/core/lib/security/secure_endpoint.h b/src/core/lib/security/secure_endpoint.h deleted file mode 100644 index ff1c6639de..0000000000 --- a/src/core/lib/security/secure_endpoint.h +++ /dev/null @@ -1,49 +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. - * - */ - -#ifndef GRPC_CORE_LIB_SECURITY_SECURE_ENDPOINT_H -#define GRPC_CORE_LIB_SECURITY_SECURE_ENDPOINT_H - -#include -#include "src/core/lib/iomgr/endpoint.h" - -struct tsi_frame_protector; - -extern int grpc_trace_secure_endpoint; - -/* Takes ownership of protector and to_wrap, and refs leftover_slices. */ -grpc_endpoint *grpc_secure_endpoint_create( - struct tsi_frame_protector *protector, grpc_endpoint *to_wrap, - gpr_slice *leftover_slices, size_t leftover_nslices); - -#endif /* GRPC_CORE_LIB_SECURITY_SECURE_ENDPOINT_H */ diff --git a/src/core/lib/security/security_connector.c b/src/core/lib/security/security_connector.c deleted file mode 100644 index 2d2023bdf5..0000000000 --- a/src/core/lib/security/security_connector.c +++ /dev/null @@ -1,838 +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 "src/core/lib/security/security_connector.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/ext/transport/chttp2/alpn/alpn.h" -#include "src/core/lib/security/credentials.h" -#include "src/core/lib/security/handshake.h" -#include "src/core/lib/security/secure_endpoint.h" -#include "src/core/lib/security/security_context.h" -#include "src/core/lib/support/env.h" -#include "src/core/lib/support/load_file.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/tsi/fake_transport_security.h" -#include "src/core/lib/tsi/ssl_transport_security.h" - -/* -- Constants. -- */ - -#ifndef INSTALL_PREFIX -static const char *installed_roots_path = "/usr/share/grpc/roots.pem"; -#else -static const char *installed_roots_path = - INSTALL_PREFIX "/share/grpc/roots.pem"; -#endif - -/* -- Overridden default roots. -- */ - -static grpc_ssl_roots_override_callback ssl_roots_override_cb = NULL; - -void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb) { - ssl_roots_override_cb = cb; -} - -/* -- Cipher suites. -- */ - -/* Defines the cipher suites that we accept by default. All these cipher suites - are compliant with HTTP2. */ -#define GRPC_SSL_CIPHER_SUITES \ - "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" \ - "SHA384:ECDHE-RSA-AES256-GCM-SHA384" - -static gpr_once cipher_suites_once = GPR_ONCE_INIT; -static const char *cipher_suites = NULL; - -static void init_cipher_suites(void) { - char *overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES"); - cipher_suites = overridden != NULL ? overridden : GRPC_SSL_CIPHER_SUITES; -} - -static const char *ssl_cipher_suites(void) { - gpr_once_init(&cipher_suites_once, init_cipher_suites); - return cipher_suites; -} - -/* -- Common methods. -- */ - -/* Returns the first property with that name. */ -const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer, - const char *name) { - size_t i; - if (peer == NULL) return NULL; - for (i = 0; i < peer->property_count; i++) { - const tsi_peer_property *property = &peer->properties[i]; - if (name == NULL && property->name == NULL) { - return property; - } - if (name != NULL && property->name != NULL && - strcmp(property->name, name) == 0) { - return property; - } - } - return NULL; -} - -void grpc_server_security_connector_shutdown( - grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector) { - grpc_security_connector_handshake_list *tmp; - gpr_mu_lock(&connector->mu); - while (connector->handshaking_handshakes) { - tmp = connector->handshaking_handshakes; - grpc_security_handshake_shutdown( - exec_ctx, connector->handshaking_handshakes->handshake); - connector->handshaking_handshakes = tmp->next; - gpr_free(tmp); - } - gpr_mu_unlock(&connector->mu); -} - -void grpc_channel_security_connector_do_handshake( - grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, - grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb, - void *user_data) { - if (sc == NULL || nonsecure_endpoint == NULL) { - cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL); - } else { - sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data); - } -} - -void grpc_server_security_connector_do_handshake( - grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, - grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint, - grpc_security_handshake_done_cb cb, void *user_data) { - if (sc == NULL || nonsecure_endpoint == NULL) { - cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL); - } else { - sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, cb, user_data); - } -} - -void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx, - grpc_security_connector *sc, - tsi_peer peer, - grpc_security_peer_check_cb cb, - void *user_data) { - if (sc == NULL) { - cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL); - tsi_peer_destruct(&peer); - } else { - sc->vtable->check_peer(exec_ctx, sc, peer, cb, user_data); - } -} - -void grpc_channel_security_connector_check_call_host( - grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, - const char *host, grpc_auth_context *auth_context, - grpc_security_call_host_check_cb cb, void *user_data) { - if (sc == NULL || sc->check_call_host == NULL) { - cb(exec_ctx, user_data, GRPC_SECURITY_ERROR); - } else { - sc->check_call_host(exec_ctx, sc, host, auth_context, cb, user_data); - } -} - -#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG -grpc_security_connector *grpc_security_connector_ref( - grpc_security_connector *sc, const char *file, int line, - const char *reason) { - if (sc == NULL) return NULL; - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "SECURITY_CONNECTOR:%p ref %d -> %d %s", sc, - (int)sc->refcount.count, (int)sc->refcount.count + 1, reason); -#else -grpc_security_connector *grpc_security_connector_ref( - grpc_security_connector *sc) { - if (sc == NULL) return NULL; -#endif - gpr_ref(&sc->refcount); - return sc; -} - -#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG -void grpc_security_connector_unref(grpc_security_connector *sc, - const char *file, int line, - const char *reason) { - if (sc == NULL) return; - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "SECURITY_CONNECTOR:%p unref %d -> %d %s", sc, - (int)sc->refcount.count, (int)sc->refcount.count - 1, reason); -#else -void grpc_security_connector_unref(grpc_security_connector *sc) { - if (sc == NULL) return; -#endif - if (gpr_unref(&sc->refcount)) sc->vtable->destroy(sc); -} - -static void connector_pointer_arg_destroy(void *p) { - GRPC_SECURITY_CONNECTOR_UNREF(p, "connector_pointer_arg"); -} - -static void *connector_pointer_arg_copy(void *p) { - return GRPC_SECURITY_CONNECTOR_REF(p, "connector_pointer_arg"); -} - -static int connector_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); } - -static const grpc_arg_pointer_vtable connector_pointer_vtable = { - connector_pointer_arg_copy, connector_pointer_arg_destroy, - connector_pointer_cmp}; - -grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) { - grpc_arg result; - result.type = GRPC_ARG_POINTER; - result.key = GRPC_SECURITY_CONNECTOR_ARG; - result.value.pointer.vtable = &connector_pointer_vtable; - result.value.pointer.p = sc; - return result; -} - -grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg) { - if (strcmp(arg->key, GRPC_SECURITY_CONNECTOR_ARG)) return NULL; - if (arg->type != GRPC_ARG_POINTER) { - gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, - GRPC_SECURITY_CONNECTOR_ARG); - return NULL; - } - return arg->value.pointer.p; -} - -grpc_security_connector *grpc_find_security_connector_in_args( - const grpc_channel_args *args) { - size_t i; - if (args == NULL) return NULL; - for (i = 0; i < args->num_args; i++) { - grpc_security_connector *sc = - grpc_security_connector_from_arg(&args->args[i]); - if (sc != NULL) return sc; - } - return NULL; -} - -/* -- Fake implementation. -- */ - -static void fake_channel_destroy(grpc_security_connector *sc) { - grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc; - grpc_call_credentials_unref(c->request_metadata_creds); - gpr_free(sc); -} - -static void fake_server_destroy(grpc_security_connector *sc) { - grpc_server_security_connector *c = (grpc_server_security_connector *)sc; - gpr_mu_destroy(&c->mu); - gpr_free(sc); -} - -static void fake_check_peer(grpc_exec_ctx *exec_ctx, - grpc_security_connector *sc, tsi_peer peer, - grpc_security_peer_check_cb cb, void *user_data) { - const char *prop_name; - grpc_security_status status = GRPC_SECURITY_OK; - grpc_auth_context *auth_context = NULL; - if (peer.property_count != 1) { - gpr_log(GPR_ERROR, "Fake peers should only have 1 property."); - status = GRPC_SECURITY_ERROR; - goto end; - } - prop_name = peer.properties[0].name; - if (prop_name == NULL || - strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) { - gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.", - prop_name == NULL ? "" : prop_name); - status = GRPC_SECURITY_ERROR; - goto end; - } - if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE, - peer.properties[0].value.length)) { - gpr_log(GPR_ERROR, "Invalid value for cert type property."); - status = GRPC_SECURITY_ERROR; - goto end; - } - auth_context = grpc_auth_context_create(NULL); - grpc_auth_context_add_cstring_property( - auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, - GRPC_FAKE_TRANSPORT_SECURITY_TYPE); - -end: - cb(exec_ctx, user_data, status, auth_context); - grpc_auth_context_unref(auth_context); - tsi_peer_destruct(&peer); -} - -static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx, - grpc_channel_security_connector *sc, - const char *host, - grpc_auth_context *auth_context, - grpc_security_call_host_check_cb cb, - void *user_data) { - cb(exec_ctx, user_data, GRPC_SECURITY_OK); -} - -static void fake_channel_do_handshake(grpc_exec_ctx *exec_ctx, - grpc_channel_security_connector *sc, - grpc_endpoint *nonsecure_endpoint, - grpc_security_handshake_done_cb cb, - void *user_data) { - grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), &sc->base, - true, nonsecure_endpoint, cb, user_data); -} - -static void fake_server_do_handshake(grpc_exec_ctx *exec_ctx, - grpc_server_security_connector *sc, - grpc_tcp_server_acceptor *acceptor, - grpc_endpoint *nonsecure_endpoint, - grpc_security_handshake_done_cb cb, - void *user_data) { - grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), &sc->base, - false, nonsecure_endpoint, cb, user_data); -} - -static grpc_security_connector_vtable fake_channel_vtable = { - fake_channel_destroy, fake_check_peer}; - -static grpc_security_connector_vtable fake_server_vtable = {fake_server_destroy, - fake_check_peer}; - -grpc_channel_security_connector *grpc_fake_channel_security_connector_create( - grpc_call_credentials *request_metadata_creds) { - grpc_channel_security_connector *c = gpr_malloc(sizeof(*c)); - memset(c, 0, sizeof(*c)); - gpr_ref_init(&c->base.refcount, 1); - c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; - c->base.vtable = &fake_channel_vtable; - c->request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds); - c->check_call_host = fake_channel_check_call_host; - c->do_handshake = fake_channel_do_handshake; - return c; -} - -grpc_server_security_connector *grpc_fake_server_security_connector_create( - void) { - grpc_server_security_connector *c = - gpr_malloc(sizeof(grpc_server_security_connector)); - memset(c, 0, sizeof(*c)); - gpr_ref_init(&c->base.refcount, 1); - c->base.vtable = &fake_server_vtable; - c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; - c->do_handshake = fake_server_do_handshake; - gpr_mu_init(&c->mu); - return c; -} - -/* --- Ssl implementation. --- */ - -typedef struct { - grpc_channel_security_connector base; - tsi_ssl_handshaker_factory *handshaker_factory; - char *target_name; - char *overridden_target_name; -} grpc_ssl_channel_security_connector; - -typedef struct { - grpc_server_security_connector base; - tsi_ssl_handshaker_factory *handshaker_factory; -} grpc_ssl_server_security_connector; - -static void ssl_channel_destroy(grpc_security_connector *sc) { - grpc_ssl_channel_security_connector *c = - (grpc_ssl_channel_security_connector *)sc; - grpc_call_credentials_unref(c->base.request_metadata_creds); - if (c->handshaker_factory != NULL) { - tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); - } - if (c->target_name != NULL) gpr_free(c->target_name); - if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name); - gpr_free(sc); -} - -static void ssl_server_destroy(grpc_security_connector *sc) { - grpc_ssl_server_security_connector *c = - (grpc_ssl_server_security_connector *)sc; - - if (c->handshaker_factory != NULL) { - tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); - } - gpr_mu_destroy(&c->base.mu); - gpr_free(sc); -} - -static grpc_security_status ssl_create_handshaker( - tsi_ssl_handshaker_factory *handshaker_factory, bool is_client, - const char *peer_name, tsi_handshaker **handshaker) { - tsi_result result = TSI_OK; - if (handshaker_factory == NULL) return GRPC_SECURITY_ERROR; - result = tsi_ssl_handshaker_factory_create_handshaker( - handshaker_factory, is_client ? peer_name : NULL, handshaker); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", - tsi_result_to_string(result)); - return GRPC_SECURITY_ERROR; - } - return GRPC_SECURITY_OK; -} - -static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx, - grpc_channel_security_connector *sc, - grpc_endpoint *nonsecure_endpoint, - grpc_security_handshake_done_cb cb, - void *user_data) { - grpc_ssl_channel_security_connector *c = - (grpc_ssl_channel_security_connector *)sc; - tsi_handshaker *handshaker; - grpc_security_status status = ssl_create_handshaker( - c->handshaker_factory, true, - c->overridden_target_name != NULL ? c->overridden_target_name - : c->target_name, - &handshaker); - if (status != GRPC_SECURITY_OK) { - cb(exec_ctx, user_data, status, NULL, NULL); - } else { - grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true, - nonsecure_endpoint, cb, user_data); - } -} - -static void ssl_server_do_handshake(grpc_exec_ctx *exec_ctx, - grpc_server_security_connector *sc, - grpc_tcp_server_acceptor *acceptor, - grpc_endpoint *nonsecure_endpoint, - grpc_security_handshake_done_cb cb, - void *user_data) { - grpc_ssl_server_security_connector *c = - (grpc_ssl_server_security_connector *)sc; - tsi_handshaker *handshaker; - grpc_security_status status = - ssl_create_handshaker(c->handshaker_factory, false, NULL, &handshaker); - if (status != GRPC_SECURITY_OK) { - cb(exec_ctx, user_data, status, NULL, NULL); - } else { - grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, false, - nonsecure_endpoint, cb, user_data); - } -} - -static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) { - char *allocated_name = NULL; - int r; - - if (strchr(peer_name, ':') != NULL) { - char *ignored_port; - gpr_split_host_port(peer_name, &allocated_name, &ignored_port); - gpr_free(ignored_port); - peer_name = allocated_name; - if (!peer_name) return 0; - } - r = tsi_ssl_peer_matches_name(peer, peer_name); - gpr_free(allocated_name); - return r; -} - -grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer) { - size_t i; - grpc_auth_context *ctx = NULL; - const char *peer_identity_property_name = NULL; - - /* The caller has checked the certificate type property. */ - GPR_ASSERT(peer->property_count >= 1); - ctx = grpc_auth_context_create(NULL); - grpc_auth_context_add_cstring_property( - ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, - GRPC_SSL_TRANSPORT_SECURITY_TYPE); - for (i = 0; i < peer->property_count; i++) { - const tsi_peer_property *prop = &peer->properties[i]; - if (prop->name == NULL) continue; - if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) { - /* If there is no subject alt name, have the CN as the identity. */ - if (peer_identity_property_name == NULL) { - peer_identity_property_name = GRPC_X509_CN_PROPERTY_NAME; - } - grpc_auth_context_add_property(ctx, GRPC_X509_CN_PROPERTY_NAME, - prop->value.data, prop->value.length); - } else if (strcmp(prop->name, - TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) { - peer_identity_property_name = GRPC_X509_SAN_PROPERTY_NAME; - grpc_auth_context_add_property(ctx, GRPC_X509_SAN_PROPERTY_NAME, - prop->value.data, prop->value.length); - } else if (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0) { - grpc_auth_context_add_property(ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME, - prop->value.data, prop->value.length); - } - } - if (peer_identity_property_name != NULL) { - GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name( - ctx, peer_identity_property_name) == 1); - } - return ctx; -} - -static grpc_security_status ssl_check_peer(grpc_security_connector *sc, - const char *peer_name, - const tsi_peer *peer, - grpc_auth_context **auth_context) { - /* Check the ALPN. */ - const tsi_peer_property *p = - tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); - if (p == NULL) { - gpr_log(GPR_ERROR, "Missing selected ALPN property."); - return GRPC_SECURITY_ERROR; - } - if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) { - gpr_log(GPR_ERROR, "Invalid ALPN value."); - return GRPC_SECURITY_ERROR; - } - - /* Check the peer name if specified. */ - if (peer_name != NULL && !ssl_host_matches_name(peer, peer_name)) { - gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name); - return GRPC_SECURITY_ERROR; - } - *auth_context = tsi_ssl_peer_to_auth_context(peer); - return GRPC_SECURITY_OK; -} - -static void ssl_channel_check_peer(grpc_exec_ctx *exec_ctx, - grpc_security_connector *sc, tsi_peer peer, - grpc_security_peer_check_cb cb, - void *user_data) { - grpc_ssl_channel_security_connector *c = - (grpc_ssl_channel_security_connector *)sc; - grpc_security_status status; - grpc_auth_context *auth_context = NULL; - status = ssl_check_peer(sc, c->overridden_target_name != NULL - ? c->overridden_target_name - : c->target_name, - &peer, &auth_context); - cb(exec_ctx, user_data, status, auth_context); - grpc_auth_context_unref(auth_context); - tsi_peer_destruct(&peer); -} - -static void ssl_server_check_peer(grpc_exec_ctx *exec_ctx, - grpc_security_connector *sc, tsi_peer peer, - grpc_security_peer_check_cb cb, - void *user_data) { - grpc_auth_context *auth_context = NULL; - grpc_security_status status = ssl_check_peer(sc, NULL, &peer, &auth_context); - tsi_peer_destruct(&peer); - cb(exec_ctx, user_data, status, auth_context); - grpc_auth_context_unref(auth_context); -} - -static void add_shallow_auth_property_to_peer(tsi_peer *peer, - const grpc_auth_property *prop, - const char *tsi_prop_name) { - tsi_peer_property *tsi_prop = &peer->properties[peer->property_count++]; - tsi_prop->name = (char *)tsi_prop_name; - tsi_prop->value.data = prop->value; - tsi_prop->value.length = prop->value_length; -} - -tsi_peer tsi_shallow_peer_from_ssl_auth_context( - const grpc_auth_context *auth_context) { - size_t max_num_props = 0; - grpc_auth_property_iterator it; - const grpc_auth_property *prop; - tsi_peer peer; - memset(&peer, 0, sizeof(peer)); - - it = grpc_auth_context_property_iterator(auth_context); - while (grpc_auth_property_iterator_next(&it) != NULL) max_num_props++; - - if (max_num_props > 0) { - peer.properties = gpr_malloc(max_num_props * sizeof(tsi_peer_property)); - it = grpc_auth_context_property_iterator(auth_context); - while ((prop = grpc_auth_property_iterator_next(&it)) != NULL) { - if (strcmp(prop->name, GRPC_X509_SAN_PROPERTY_NAME) == 0) { - add_shallow_auth_property_to_peer( - &peer, prop, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY); - } else if (strcmp(prop->name, GRPC_X509_CN_PROPERTY_NAME) == 0) { - add_shallow_auth_property_to_peer( - &peer, prop, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY); - } else if (strcmp(prop->name, GRPC_X509_PEM_CERT_PROPERTY_NAME) == 0) { - add_shallow_auth_property_to_peer(&peer, prop, - TSI_X509_PEM_CERT_PROPERTY); - } - } - } - return peer; -} - -void tsi_shallow_peer_destruct(tsi_peer *peer) { - if (peer->properties != NULL) gpr_free(peer->properties); -} - -static void ssl_channel_check_call_host(grpc_exec_ctx *exec_ctx, - grpc_channel_security_connector *sc, - const char *host, - grpc_auth_context *auth_context, - grpc_security_call_host_check_cb cb, - void *user_data) { - grpc_ssl_channel_security_connector *c = - (grpc_ssl_channel_security_connector *)sc; - grpc_security_status status = GRPC_SECURITY_ERROR; - tsi_peer peer = tsi_shallow_peer_from_ssl_auth_context(auth_context); - if (ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK; - - /* If the target name was overridden, then the original target_name was - 'checked' transitively during the previous peer check at the end of the - handshake. */ - if (c->overridden_target_name != NULL && strcmp(host, c->target_name) == 0) { - status = GRPC_SECURITY_OK; - } - cb(exec_ctx, user_data, status); - tsi_shallow_peer_destruct(&peer); -} - -static grpc_security_connector_vtable ssl_channel_vtable = { - ssl_channel_destroy, ssl_channel_check_peer}; - -static grpc_security_connector_vtable ssl_server_vtable = { - ssl_server_destroy, ssl_server_check_peer}; - -static gpr_slice compute_default_pem_root_certs_once(void) { - gpr_slice result = gpr_empty_slice(); - - /* First try to load the roots from the environment. */ - char *default_root_certs_path = - gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); - if (default_root_certs_path != NULL) { - result = gpr_load_file(default_root_certs_path, 0, NULL); - gpr_free(default_root_certs_path); - } - - /* Try overridden roots if needed. */ - grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL; - if (GPR_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != NULL) { - char *pem_root_certs = NULL; - ovrd_res = ssl_roots_override_cb(&pem_root_certs); - if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) { - GPR_ASSERT(pem_root_certs != NULL); - result = gpr_slice_new(pem_root_certs, strlen(pem_root_certs), gpr_free); - } - } - - /* Fall back to installed certs if needed. */ - if (GPR_SLICE_IS_EMPTY(result) && - ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { - result = gpr_load_file(installed_roots_path, 0, NULL); - } - return result; -} - -static gpr_slice default_pem_root_certs; - -static void init_default_pem_root_certs(void) { - default_pem_root_certs = compute_default_pem_root_certs_once(); -} - -gpr_slice grpc_get_default_ssl_roots_for_testing(void) { - return compute_default_pem_root_certs_once(); -} - -static tsi_client_certificate_request_type -get_tsi_client_certificate_request_type( - grpc_ssl_client_certificate_request_type grpc_request_type) { - switch (grpc_request_type) { - case GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE: - return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; - - case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: - return TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; - - case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: - return TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY; - - case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: - return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; - - case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: - return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY; - - default: - // Is this a sane default - return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; - } -} - -size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) { - /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in - loading all the roots once for the lifetime of the process. */ - static gpr_once once = GPR_ONCE_INIT; - gpr_once_init(&once, init_default_pem_root_certs); - *pem_root_certs = GPR_SLICE_START_PTR(default_pem_root_certs); - return GPR_SLICE_LENGTH(default_pem_root_certs); -} - -grpc_security_status grpc_ssl_channel_security_connector_create( - grpc_call_credentials *request_metadata_creds, - const grpc_ssl_config *config, const char *target_name, - const char *overridden_target_name, grpc_channel_security_connector **sc) { - size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions(); - const unsigned char **alpn_protocol_strings = - gpr_malloc(sizeof(const char *) * num_alpn_protocols); - unsigned char *alpn_protocol_string_lengths = - gpr_malloc(sizeof(unsigned char) * num_alpn_protocols); - tsi_result result = TSI_OK; - grpc_ssl_channel_security_connector *c; - size_t i; - const unsigned char *pem_root_certs; - size_t pem_root_certs_size; - char *port; - - for (i = 0; i < num_alpn_protocols; i++) { - alpn_protocol_strings[i] = - (const unsigned char *)grpc_chttp2_get_alpn_version_index(i); - alpn_protocol_string_lengths[i] = - (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i)); - } - - if (config == NULL || target_name == NULL) { - gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name."); - goto error; - } - if (config->pem_root_certs == NULL) { - pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs); - if (pem_root_certs == NULL || pem_root_certs_size == 0) { - gpr_log(GPR_ERROR, "Could not get default pem root certs."); - goto error; - } - } else { - pem_root_certs = config->pem_root_certs; - pem_root_certs_size = config->pem_root_certs_size; - } - - c = gpr_malloc(sizeof(grpc_ssl_channel_security_connector)); - memset(c, 0, sizeof(grpc_ssl_channel_security_connector)); - - gpr_ref_init(&c->base.base.refcount, 1); - c->base.base.vtable = &ssl_channel_vtable; - c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; - c->base.request_metadata_creds = - grpc_call_credentials_ref(request_metadata_creds); - c->base.check_call_host = ssl_channel_check_call_host; - c->base.do_handshake = ssl_channel_do_handshake; - gpr_split_host_port(target_name, &c->target_name, &port); - gpr_free(port); - if (overridden_target_name != NULL) { - c->overridden_target_name = gpr_strdup(overridden_target_name); - } - result = tsi_create_ssl_client_handshaker_factory( - config->pem_private_key, config->pem_private_key_size, - config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs, - pem_root_certs_size, ssl_cipher_suites(), alpn_protocol_strings, - alpn_protocol_string_lengths, (uint16_t)num_alpn_protocols, - &c->handshaker_factory); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", - tsi_result_to_string(result)); - ssl_channel_destroy(&c->base.base); - *sc = NULL; - goto error; - } - *sc = &c->base; - gpr_free((void *)alpn_protocol_strings); - gpr_free(alpn_protocol_string_lengths); - return GRPC_SECURITY_OK; - -error: - gpr_free((void *)alpn_protocol_strings); - gpr_free(alpn_protocol_string_lengths); - return GRPC_SECURITY_ERROR; -} - -grpc_security_status grpc_ssl_server_security_connector_create( - const grpc_ssl_server_config *config, grpc_server_security_connector **sc) { - size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions(); - const unsigned char **alpn_protocol_strings = - gpr_malloc(sizeof(const char *) * num_alpn_protocols); - unsigned char *alpn_protocol_string_lengths = - gpr_malloc(sizeof(unsigned char) * num_alpn_protocols); - tsi_result result = TSI_OK; - grpc_ssl_server_security_connector *c; - size_t i; - - for (i = 0; i < num_alpn_protocols; i++) { - alpn_protocol_strings[i] = - (const unsigned char *)grpc_chttp2_get_alpn_version_index(i); - alpn_protocol_string_lengths[i] = - (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i)); - } - - if (config == NULL || config->num_key_cert_pairs == 0) { - gpr_log(GPR_ERROR, "An SSL server needs a key and a cert."); - goto error; - } - c = gpr_malloc(sizeof(grpc_ssl_server_security_connector)); - memset(c, 0, sizeof(grpc_ssl_server_security_connector)); - - gpr_ref_init(&c->base.base.refcount, 1); - c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; - c->base.base.vtable = &ssl_server_vtable; - result = tsi_create_ssl_server_handshaker_factory_ex( - (const unsigned char **)config->pem_private_keys, - config->pem_private_keys_sizes, - (const unsigned char **)config->pem_cert_chains, - config->pem_cert_chains_sizes, config->num_key_cert_pairs, - config->pem_root_certs, config->pem_root_certs_size, - get_tsi_client_certificate_request_type( - config->client_certificate_request), - ssl_cipher_suites(), alpn_protocol_strings, alpn_protocol_string_lengths, - (uint16_t)num_alpn_protocols, &c->handshaker_factory); - if (result != TSI_OK) { - gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", - tsi_result_to_string(result)); - ssl_server_destroy(&c->base.base); - *sc = NULL; - goto error; - } - gpr_mu_init(&c->base.mu); - c->base.do_handshake = ssl_server_do_handshake; - *sc = &c->base; - gpr_free((void *)alpn_protocol_strings); - gpr_free(alpn_protocol_string_lengths); - return GRPC_SECURITY_OK; - -error: - gpr_free((void *)alpn_protocol_strings); - gpr_free(alpn_protocol_string_lengths); - return GRPC_SECURITY_ERROR; -} diff --git a/src/core/lib/security/security_connector.h b/src/core/lib/security/security_connector.h deleted file mode 100644 index 2c893cd5e9..0000000000 --- a/src/core/lib/security/security_connector.h +++ /dev/null @@ -1,266 +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. - * - */ - -#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_H -#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_H - -#include -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/iomgr/tcp_server.h" -#include "src/core/lib/tsi/transport_security_interface.h" - -/* --- status enum. --- */ - -typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status; - -/* --- URL schemes. --- */ - -#define GRPC_SSL_URL_SCHEME "https" -#define GRPC_FAKE_SECURITY_URL_SCHEME "http+fake_security" - -/* --- security_connector object. --- - - A security connector object represents away to configure the underlying - transport security mechanism and check the resulting trusted peer. */ - -typedef struct grpc_security_connector grpc_security_connector; - -#define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector" - -typedef void (*grpc_security_peer_check_cb)(grpc_exec_ctx *exec_ctx, - void *user_data, - grpc_security_status status, - grpc_auth_context *auth_context); - -/* Ownership of the secure_endpoint is transfered. */ -typedef void (*grpc_security_handshake_done_cb)( - grpc_exec_ctx *exec_ctx, void *user_data, grpc_security_status status, - grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context); - -typedef struct { - void (*destroy)(grpc_security_connector *sc); - void (*check_peer)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, - tsi_peer peer, grpc_security_peer_check_cb cb, - void *user_data); -} grpc_security_connector_vtable; - -typedef struct grpc_security_connector_handshake_list { - void *handshake; - struct grpc_security_connector_handshake_list *next; -} grpc_security_connector_handshake_list; - -struct grpc_security_connector { - const grpc_security_connector_vtable *vtable; - gpr_refcount refcount; - const char *url_scheme; -}; - -/* Refcounting. */ -#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG -#define GRPC_SECURITY_CONNECTOR_REF(p, r) \ - grpc_security_connector_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) \ - grpc_security_connector_unref((p), __FILE__, __LINE__, (r)) -grpc_security_connector *grpc_security_connector_ref( - grpc_security_connector *policy, const char *file, int line, - const char *reason); -void grpc_security_connector_unref(grpc_security_connector *policy, - const char *file, int line, - const char *reason); -#else -#define GRPC_SECURITY_CONNECTOR_REF(p, r) grpc_security_connector_ref((p)) -#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) grpc_security_connector_unref((p)) -grpc_security_connector *grpc_security_connector_ref( - grpc_security_connector *policy); -void grpc_security_connector_unref(grpc_security_connector *policy); -#endif - -/* Check the peer. Callee takes ownership of the peer object. - The callback will include the resulting auth_context. */ -void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx, - grpc_security_connector *sc, - tsi_peer peer, - grpc_security_peer_check_cb cb, - void *user_data); - -/* Util to encapsulate the connector in a channel arg. */ -grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc); - -/* Util to get the connector from a channel arg. */ -grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg); - -/* Util to find the connector from channel args. */ -grpc_security_connector *grpc_find_security_connector_in_args( - const grpc_channel_args *args); - -/* --- channel_security_connector object. --- - - A channel security connector object represents away to configure the - underlying transport security mechanism on the client side. */ - -typedef struct grpc_channel_security_connector grpc_channel_security_connector; - -typedef void (*grpc_security_call_host_check_cb)(grpc_exec_ctx *exec_ctx, - void *user_data, - grpc_security_status status); - -struct grpc_channel_security_connector { - grpc_security_connector base; - grpc_call_credentials *request_metadata_creds; - void (*check_call_host)(grpc_exec_ctx *exec_ctx, - grpc_channel_security_connector *sc, const char *host, - grpc_auth_context *auth_context, - grpc_security_call_host_check_cb cb, void *user_data); - void (*do_handshake)(grpc_exec_ctx *exec_ctx, - grpc_channel_security_connector *sc, - grpc_endpoint *nonsecure_endpoint, - grpc_security_handshake_done_cb cb, void *user_data); -}; - -/* Checks that the host that will be set for a call is acceptable. */ -void grpc_channel_security_connector_check_call_host( - grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, - const char *host, grpc_auth_context *auth_context, - grpc_security_call_host_check_cb cb, void *user_data); - -/* Handshake. */ -void grpc_channel_security_connector_do_handshake( - grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector, - grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb, - void *user_data); - -/* --- server_security_connector object. --- - - A server security connector object represents away to configure the - underlying transport security mechanism on the server side. */ - -typedef struct grpc_server_security_connector grpc_server_security_connector; - -struct grpc_server_security_connector { - grpc_security_connector base; - gpr_mu mu; - grpc_security_connector_handshake_list *handshaking_handshakes; - const grpc_channel_args *channel_args; - void (*do_handshake)(grpc_exec_ctx *exec_ctx, - grpc_server_security_connector *sc, - grpc_tcp_server_acceptor *acceptor, - grpc_endpoint *nonsecure_endpoint, - grpc_security_handshake_done_cb cb, void *user_data); -}; - -void grpc_server_security_connector_do_handshake( - grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, - grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint, - grpc_security_handshake_done_cb cb, void *user_data); - -void grpc_server_security_connector_shutdown( - grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector); - -/* --- Creation security connectors. --- */ - -/* For TESTING ONLY! - Creates a fake connector that emulates real channel security. */ -grpc_channel_security_connector *grpc_fake_channel_security_connector_create( - grpc_call_credentials *request_metadata_creds); - -/* For TESTING ONLY! - Creates a fake connector that emulates real server security. */ -grpc_server_security_connector *grpc_fake_server_security_connector_create( - void); - -/* Config for ssl clients. */ -typedef struct { - unsigned char *pem_private_key; - size_t pem_private_key_size; - unsigned char *pem_cert_chain; - size_t pem_cert_chain_size; - unsigned char *pem_root_certs; - size_t pem_root_certs_size; -} grpc_ssl_config; - -/* Creates an SSL channel_security_connector. - - request_metadata_creds is the credentials object which metadata - will be sent with each request. This parameter can be NULL. - - config is the SSL config to be used for the SSL channel establishment. - - is_client should be 0 for a server or a non-0 value for a client. - - secure_peer_name is the secure peer name that should be checked in - grpc_channel_security_connector_check_peer. This parameter may be NULL in - which case the peer name will not be checked. Note that if this parameter - is not NULL, then, pem_root_certs should not be NULL either. - - sc is a pointer on the connector to be created. - This function returns GRPC_SECURITY_OK in case of success or a - specific error code otherwise. -*/ -grpc_security_status grpc_ssl_channel_security_connector_create( - grpc_call_credentials *request_metadata_creds, - const grpc_ssl_config *config, const char *target_name, - const char *overridden_target_name, grpc_channel_security_connector **sc); - -/* Gets the default ssl roots. */ -size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs); - -/* Exposed for TESTING ONLY!. */ -gpr_slice grpc_get_default_ssl_roots_for_testing(void); - -/* Config for ssl servers. */ -typedef struct { - unsigned char **pem_private_keys; - size_t *pem_private_keys_sizes; - unsigned char **pem_cert_chains; - size_t *pem_cert_chains_sizes; - size_t num_key_cert_pairs; - unsigned char *pem_root_certs; - size_t pem_root_certs_size; - grpc_ssl_client_certificate_request_type client_certificate_request; -} grpc_ssl_server_config; - -/* Creates an SSL server_security_connector. - - config is the SSL config to be used for the SSL channel establishment. - - sc is a pointer on the connector to be created. - This function returns GRPC_SECURITY_OK in case of success or a - specific error code otherwise. -*/ -grpc_security_status grpc_ssl_server_security_connector_create( - const grpc_ssl_server_config *config, grpc_server_security_connector **sc); - -/* Util. */ -const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer, - const char *name); - -/* Exposed for testing only. */ -grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer); -tsi_peer tsi_shallow_peer_from_ssl_auth_context( - const grpc_auth_context *auth_context); -void tsi_shallow_peer_destruct(tsi_peer *peer); - -#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_H */ diff --git a/src/core/lib/security/security_context.c b/src/core/lib/security/security_context.c deleted file mode 100644 index 343e0b5b8b..0000000000 --- a/src/core/lib/security/security_context.c +++ /dev/null @@ -1,347 +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 - -#include "src/core/lib/security/security_context.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/api_trace.h" -#include "src/core/lib/surface/call.h" - -#include -#include -#include -#include - -/* --- grpc_call --- */ - -grpc_call_error grpc_call_set_credentials(grpc_call *call, - grpc_call_credentials *creds) { - grpc_client_security_context *ctx = NULL; - GRPC_API_TRACE("grpc_call_set_credentials(call=%p, creds=%p)", 2, - (call, creds)); - if (!grpc_call_is_client(call)) { - gpr_log(GPR_ERROR, "Method is client-side only."); - return GRPC_CALL_ERROR_NOT_ON_SERVER; - } - ctx = (grpc_client_security_context *)grpc_call_context_get( - call, GRPC_CONTEXT_SECURITY); - if (ctx == NULL) { - ctx = grpc_client_security_context_create(); - ctx->creds = grpc_call_credentials_ref(creds); - grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx, - grpc_client_security_context_destroy); - } else { - grpc_call_credentials_unref(ctx->creds); - ctx->creds = grpc_call_credentials_ref(creds); - } - return GRPC_CALL_OK; -} - -grpc_auth_context *grpc_call_auth_context(grpc_call *call) { - void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY); - GRPC_API_TRACE("grpc_call_auth_context(call=%p)", 1, (call)); - if (sec_ctx == NULL) return NULL; - return grpc_call_is_client(call) - ? GRPC_AUTH_CONTEXT_REF( - ((grpc_client_security_context *)sec_ctx)->auth_context, - "grpc_call_auth_context client") - : GRPC_AUTH_CONTEXT_REF( - ((grpc_server_security_context *)sec_ctx)->auth_context, - "grpc_call_auth_context server"); -} - -void grpc_auth_context_release(grpc_auth_context *context) { - GRPC_API_TRACE("grpc_auth_context_release(context=%p)", 1, (context)); - GRPC_AUTH_CONTEXT_UNREF(context, "grpc_auth_context_unref"); -} - -/* --- grpc_client_security_context --- */ - -grpc_client_security_context *grpc_client_security_context_create(void) { - grpc_client_security_context *ctx = - gpr_malloc(sizeof(grpc_client_security_context)); - memset(ctx, 0, sizeof(grpc_client_security_context)); - return ctx; -} - -void grpc_client_security_context_destroy(void *ctx) { - grpc_client_security_context *c = (grpc_client_security_context *)ctx; - grpc_call_credentials_unref(c->creds); - GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context"); - gpr_free(ctx); -} - -/* --- grpc_server_security_context --- */ - -grpc_server_security_context *grpc_server_security_context_create(void) { - grpc_server_security_context *ctx = - gpr_malloc(sizeof(grpc_server_security_context)); - memset(ctx, 0, sizeof(grpc_server_security_context)); - return ctx; -} - -void grpc_server_security_context_destroy(void *ctx) { - grpc_server_security_context *c = (grpc_server_security_context *)ctx; - GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "server_security_context"); - gpr_free(ctx); -} - -/* --- grpc_auth_context --- */ - -static grpc_auth_property_iterator empty_iterator = {NULL, 0, NULL}; - -grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained) { - grpc_auth_context *ctx = gpr_malloc(sizeof(grpc_auth_context)); - memset(ctx, 0, sizeof(grpc_auth_context)); - gpr_ref_init(&ctx->refcount, 1); - if (chained != NULL) { - ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained"); - ctx->peer_identity_property_name = - ctx->chained->peer_identity_property_name; - } - return ctx; -} - -#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG -grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx, - const char *file, int line, - const char *reason) { - if (ctx == NULL) return NULL; - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "AUTH_CONTEXT:%p ref %d -> %d %s", ctx, (int)ctx->refcount.count, - (int)ctx->refcount.count + 1, reason); -#else -grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *ctx) { - if (ctx == NULL) return NULL; -#endif - gpr_ref(&ctx->refcount); - return ctx; -} - -#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG -void grpc_auth_context_unref(grpc_auth_context *ctx, const char *file, int line, - const char *reason) { - if (ctx == NULL) return; - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "AUTH_CONTEXT:%p unref %d -> %d %s", ctx, (int)ctx->refcount.count, - (int)ctx->refcount.count - 1, reason); -#else -void grpc_auth_context_unref(grpc_auth_context *ctx) { - if (ctx == NULL) return; -#endif - if (gpr_unref(&ctx->refcount)) { - size_t i; - GRPC_AUTH_CONTEXT_UNREF(ctx->chained, "chained"); - if (ctx->properties.array != NULL) { - for (i = 0; i < ctx->properties.count; i++) { - grpc_auth_property_reset(&ctx->properties.array[i]); - } - gpr_free(ctx->properties.array); - } - gpr_free(ctx); - } -} - -const char *grpc_auth_context_peer_identity_property_name( - const grpc_auth_context *ctx) { - GRPC_API_TRACE("grpc_auth_context_peer_identity_property_name(ctx=%p)", 1, - (ctx)); - return ctx->peer_identity_property_name; -} - -int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx, - const char *name) { - grpc_auth_property_iterator it = - grpc_auth_context_find_properties_by_name(ctx, name); - const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); - GRPC_API_TRACE( - "grpc_auth_context_set_peer_identity_property_name(ctx=%p, name=%s)", 2, - (ctx, name)); - if (prop == NULL) { - gpr_log(GPR_ERROR, "Property name %s not found in auth context.", - name != NULL ? name : "NULL"); - return 0; - } - ctx->peer_identity_property_name = prop->name; - return 1; -} - -int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx) { - GRPC_API_TRACE("grpc_auth_context_peer_is_authenticated(ctx=%p)", 1, (ctx)); - return ctx->peer_identity_property_name == NULL ? 0 : 1; -} - -grpc_auth_property_iterator grpc_auth_context_property_iterator( - const grpc_auth_context *ctx) { - grpc_auth_property_iterator it = empty_iterator; - GRPC_API_TRACE("grpc_auth_context_property_iterator(ctx=%p)", 1, (ctx)); - if (ctx == NULL) return it; - it.ctx = ctx; - return it; -} - -const grpc_auth_property *grpc_auth_property_iterator_next( - grpc_auth_property_iterator *it) { - GRPC_API_TRACE("grpc_auth_property_iterator_next(it=%p)", 1, (it)); - if (it == NULL || it->ctx == NULL) return NULL; - while (it->index == it->ctx->properties.count) { - if (it->ctx->chained == NULL) return NULL; - it->ctx = it->ctx->chained; - it->index = 0; - } - if (it->name == NULL) { - return &it->ctx->properties.array[it->index++]; - } else { - while (it->index < it->ctx->properties.count) { - const grpc_auth_property *prop = &it->ctx->properties.array[it->index++]; - GPR_ASSERT(prop->name != NULL); - if (strcmp(it->name, prop->name) == 0) { - return prop; - } - } - /* We could not find the name, try another round. */ - return grpc_auth_property_iterator_next(it); - } -} - -grpc_auth_property_iterator grpc_auth_context_find_properties_by_name( - const grpc_auth_context *ctx, const char *name) { - grpc_auth_property_iterator it = empty_iterator; - GRPC_API_TRACE("grpc_auth_context_find_properties_by_name(ctx=%p, name=%s)", - 2, (ctx, name)); - if (ctx == NULL || name == NULL) return empty_iterator; - it.ctx = ctx; - it.name = name; - return it; -} - -grpc_auth_property_iterator grpc_auth_context_peer_identity( - const grpc_auth_context *ctx) { - GRPC_API_TRACE("grpc_auth_context_peer_identity(ctx=%p)", 1, (ctx)); - if (ctx == NULL) return empty_iterator; - return grpc_auth_context_find_properties_by_name( - ctx, ctx->peer_identity_property_name); -} - -static void ensure_auth_context_capacity(grpc_auth_context *ctx) { - if (ctx->properties.count == ctx->properties.capacity) { - ctx->properties.capacity = - GPR_MAX(ctx->properties.capacity + 8, ctx->properties.capacity * 2); - ctx->properties.array = - gpr_realloc(ctx->properties.array, - ctx->properties.capacity * sizeof(grpc_auth_property)); - } -} - -void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name, - const char *value, size_t value_length) { - grpc_auth_property *prop; - GRPC_API_TRACE( - "grpc_auth_context_add_property(ctx=%p, name=%s, value=%*.*s, " - "value_length=%lu)", - 6, (ctx, name, (int)value_length, (int)value_length, value, - (unsigned long)value_length)); - ensure_auth_context_capacity(ctx); - prop = &ctx->properties.array[ctx->properties.count++]; - prop->name = gpr_strdup(name); - prop->value = gpr_malloc(value_length + 1); - memcpy(prop->value, value, value_length); - prop->value[value_length] = '\0'; - prop->value_length = value_length; -} - -void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx, - const char *name, - const char *value) { - grpc_auth_property *prop; - GRPC_API_TRACE( - "grpc_auth_context_add_cstring_property(ctx=%p, name=%s, value=%s)", 3, - (ctx, name, value)); - ensure_auth_context_capacity(ctx); - prop = &ctx->properties.array[ctx->properties.count++]; - prop->name = gpr_strdup(name); - prop->value = gpr_strdup(value); - prop->value_length = strlen(value); -} - -void grpc_auth_property_reset(grpc_auth_property *property) { - gpr_free(property->name); - gpr_free(property->value); - memset(property, 0, sizeof(grpc_auth_property)); -} - -static void auth_context_pointer_arg_destroy(void *p) { - GRPC_AUTH_CONTEXT_UNREF(p, "auth_context_pointer_arg"); -} - -static void *auth_context_pointer_arg_copy(void *p) { - return GRPC_AUTH_CONTEXT_REF(p, "auth_context_pointer_arg"); -} - -static int auth_context_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); } - -static const grpc_arg_pointer_vtable auth_context_pointer_vtable = { - auth_context_pointer_arg_copy, auth_context_pointer_arg_destroy, - auth_context_pointer_cmp}; - -grpc_arg grpc_auth_context_to_arg(grpc_auth_context *p) { - grpc_arg arg; - memset(&arg, 0, sizeof(grpc_arg)); - arg.type = GRPC_ARG_POINTER; - arg.key = GRPC_AUTH_CONTEXT_ARG; - arg.value.pointer.p = p; - arg.value.pointer.vtable = &auth_context_pointer_vtable; - return arg; -} - -grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg) { - if (strcmp(arg->key, GRPC_AUTH_CONTEXT_ARG) != 0) return NULL; - if (arg->type != GRPC_ARG_POINTER) { - gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, - GRPC_AUTH_CONTEXT_ARG); - return NULL; - } - return arg->value.pointer.p; -} - -grpc_auth_context *grpc_find_auth_context_in_args( - const grpc_channel_args *args) { - size_t i; - if (args == NULL) return NULL; - for (i = 0; i < args->num_args; i++) { - grpc_auth_context *p = grpc_auth_context_from_arg(&args->args[i]); - if (p != NULL) return p; - } - return NULL; -} diff --git a/src/core/lib/security/security_context.h b/src/core/lib/security/security_context.h deleted file mode 100644 index 81161ec47d..0000000000 --- a/src/core/lib/security/security_context.h +++ /dev/null @@ -1,114 +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. - * - */ - -#ifndef GRPC_CORE_LIB_SECURITY_SECURITY_CONTEXT_H -#define GRPC_CORE_LIB_SECURITY_SECURITY_CONTEXT_H - -#include "src/core/lib/iomgr/pollset.h" -#include "src/core/lib/security/credentials.h" - -/* --- grpc_auth_context --- - - High level authentication context object. Can optionally be chained. */ - -/* Property names are always NULL terminated. */ - -typedef struct { - grpc_auth_property *array; - size_t count; - size_t capacity; -} grpc_auth_property_array; - -struct grpc_auth_context { - struct grpc_auth_context *chained; - grpc_auth_property_array properties; - gpr_refcount refcount; - const char *peer_identity_property_name; - grpc_pollset *pollset; -}; - -/* Creation. */ -grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained); - -/* Refcounting. */ -#ifdef GRPC_AUTH_CONTEXT_REFCOUNT_DEBUG -#define GRPC_AUTH_CONTEXT_REF(p, r) \ - grpc_auth_context_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_AUTH_CONTEXT_UNREF(p, r) \ - grpc_auth_context_unref((p), __FILE__, __LINE__, (r)) -grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy, - const char *file, int line, - const char *reason); -void grpc_auth_context_unref(grpc_auth_context *policy, const char *file, - int line, const char *reason); -#else -#define GRPC_AUTH_CONTEXT_REF(p, r) grpc_auth_context_ref((p)) -#define GRPC_AUTH_CONTEXT_UNREF(p, r) grpc_auth_context_unref((p)) -grpc_auth_context *grpc_auth_context_ref(grpc_auth_context *policy); -void grpc_auth_context_unref(grpc_auth_context *policy); -#endif - -void grpc_auth_property_reset(grpc_auth_property *property); - -/* --- grpc_client_security_context --- - - Internal client-side security context. */ - -typedef struct { - grpc_call_credentials *creds; - grpc_auth_context *auth_context; -} grpc_client_security_context; - -grpc_client_security_context *grpc_client_security_context_create(void); -void grpc_client_security_context_destroy(void *ctx); - -/* --- grpc_server_security_context --- - - Internal server-side security context. */ - -typedef struct { - grpc_auth_context *auth_context; -} grpc_server_security_context; - -grpc_server_security_context *grpc_server_security_context_create(void); -void grpc_server_security_context_destroy(void *ctx); - -/* --- Channel args for auth context --- */ -#define GRPC_AUTH_CONTEXT_ARG "grpc.auth_context" - -grpc_arg grpc_auth_context_to_arg(grpc_auth_context *c); -grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg); -grpc_auth_context *grpc_find_auth_context_in_args( - const grpc_channel_args *args); - -#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONTEXT_H */ diff --git a/src/core/lib/security/server_auth_filter.c b/src/core/lib/security/server_auth_filter.c deleted file mode 100644 index 3320497d21..0000000000 --- a/src/core/lib/security/server_auth_filter.c +++ /dev/null @@ -1,264 +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 - -#include "src/core/lib/security/auth_filters.h" -#include "src/core/lib/security/credentials.h" -#include "src/core/lib/security/security_context.h" - -#include -#include - -typedef struct call_data { - grpc_metadata_batch *recv_initial_metadata; - /* Closure to call when finished with the auth_on_recv hook. */ - grpc_closure *on_done_recv; - /* Receive closures are chained: we inject this closure as the on_done_recv - up-call on transport_op, and remember to call our on_done_recv member after - handling it. */ - grpc_closure auth_on_recv; - grpc_transport_stream_op transport_op; - grpc_metadata_array md; - const grpc_metadata *consumed_md; - size_t num_consumed_md; - grpc_auth_context *auth_context; -} call_data; - -typedef struct channel_data { - grpc_auth_context *auth_context; - grpc_server_credentials *creds; -} channel_data; - -static grpc_metadata_array metadata_batch_to_md_array( - const grpc_metadata_batch *batch) { - grpc_linked_mdelem *l; - grpc_metadata_array result; - grpc_metadata_array_init(&result); - for (l = batch->list.head; l != NULL; l = l->next) { - grpc_metadata *usr_md = NULL; - grpc_mdelem *md = l->md; - grpc_mdstr *key = md->key; - grpc_mdstr *value = md->value; - if (result.count == result.capacity) { - result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2); - result.metadata = - gpr_realloc(result.metadata, result.capacity * sizeof(grpc_metadata)); - } - usr_md = &result.metadata[result.count++]; - usr_md->key = grpc_mdstr_as_c_string(key); - usr_md->value = grpc_mdstr_as_c_string(value); - usr_md->value_length = GPR_SLICE_LENGTH(value->slice); - } - return result; -} - -static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) { - grpc_call_element *elem = user_data; - call_data *calld = elem->call_data; - size_t i; - for (i = 0; i < calld->num_consumed_md; i++) { - const grpc_metadata *consumed_md = &calld->consumed_md[i]; - /* Maybe we could do a pointer comparison but we do not have any guarantee - that the metadata processor used the same pointers for consumed_md in the - callback. */ - if (GPR_SLICE_LENGTH(md->key->slice) != strlen(consumed_md->key) || - GPR_SLICE_LENGTH(md->value->slice) != consumed_md->value_length) { - continue; - } - if (memcmp(GPR_SLICE_START_PTR(md->key->slice), consumed_md->key, - GPR_SLICE_LENGTH(md->key->slice)) == 0 && - memcmp(GPR_SLICE_START_PTR(md->value->slice), consumed_md->value, - GPR_SLICE_LENGTH(md->value->slice)) == 0) { - return NULL; /* Delete. */ - } - } - return md; -} - -/* called from application code */ -static void on_md_processing_done( - void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md, - const grpc_metadata *response_md, size_t num_response_md, - grpc_status_code status, const char *error_details) { - grpc_call_element *elem = user_data; - call_data *calld = elem->call_data; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - - /* TODO(jboeuf): Implement support for response_md. */ - if (response_md != NULL && num_response_md > 0) { - gpr_log(GPR_INFO, - "response_md in auth metadata processing not supported for now. " - "Ignoring..."); - } - - if (status == GRPC_STATUS_OK) { - calld->consumed_md = consumed_md; - calld->num_consumed_md = num_consumed_md; - grpc_metadata_batch_filter(calld->recv_initial_metadata, remove_consumed_md, - elem); - grpc_metadata_array_destroy(&calld->md); - calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 1); - } else { - gpr_slice message; - grpc_transport_stream_op close_op; - memset(&close_op, 0, sizeof(close_op)); - grpc_metadata_array_destroy(&calld->md); - error_details = error_details != NULL - ? error_details - : "Authentication metadata processing failed."; - message = gpr_slice_from_copied_string(error_details); - calld->transport_op.send_initial_metadata = NULL; - if (calld->transport_op.send_message != NULL) { - grpc_byte_stream_destroy(&exec_ctx, calld->transport_op.send_message); - calld->transport_op.send_message = NULL; - } - calld->transport_op.send_trailing_metadata = NULL; - grpc_transport_stream_op_add_close(&close_op, status, &message); - grpc_call_next_op(&exec_ctx, elem, &close_op); - calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 0); - } - - grpc_exec_ctx_finish(&exec_ctx); -} - -static void auth_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, - bool success) { - grpc_call_element *elem = user_data; - call_data *calld = elem->call_data; - channel_data *chand = elem->channel_data; - if (success) { - if (chand->creds->processor.process != NULL) { - calld->md = metadata_batch_to_md_array(calld->recv_initial_metadata); - chand->creds->processor.process( - chand->creds->processor.state, calld->auth_context, - calld->md.metadata, calld->md.count, on_md_processing_done, elem); - return; - } - } - calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success); -} - -static void set_recv_ops_md_callbacks(grpc_call_element *elem, - grpc_transport_stream_op *op) { - call_data *calld = elem->call_data; - - if (op->recv_initial_metadata != NULL) { - /* substitute our callback for the higher callback */ - calld->recv_initial_metadata = op->recv_initial_metadata; - calld->on_done_recv = op->recv_initial_metadata_ready; - op->recv_initial_metadata_ready = &calld->auth_on_recv; - calld->transport_op = *op; - } -} - -/* Called either: - - in response to an API call (or similar) from above, to send something - - a network event (or similar) from below, to receive something - op contains type and call direction information, in addition to the data - that is being sent or received. */ -static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, - grpc_call_element *elem, - grpc_transport_stream_op *op) { - set_recv_ops_md_callbacks(elem, op); - grpc_call_next_op(exec_ctx, elem, op); -} - -/* Constructor for call_data */ -static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_call_element_args *args) { - /* grab pointers to our data from the call element */ - call_data *calld = elem->call_data; - channel_data *chand = elem->channel_data; - grpc_server_security_context *server_ctx = NULL; - - /* initialize members */ - memset(calld, 0, sizeof(*calld)); - grpc_closure_init(&calld->auth_on_recv, auth_on_recv, elem); - - if (args->context[GRPC_CONTEXT_SECURITY].value != NULL) { - args->context[GRPC_CONTEXT_SECURITY].destroy( - args->context[GRPC_CONTEXT_SECURITY].value); - } - - server_ctx = grpc_server_security_context_create(); - server_ctx->auth_context = grpc_auth_context_create(chand->auth_context); - calld->auth_context = server_ctx->auth_context; - - args->context[GRPC_CONTEXT_SECURITY].value = server_ctx; - args->context[GRPC_CONTEXT_SECURITY].destroy = - grpc_server_security_context_destroy; -} - -static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - grpc_pollset *pollset) {} - -/* Destructor for call_data */ -static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, - void *ignored) {} - -/* Constructor for channel_data */ -static void init_channel_elem(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem, - grpc_channel_element_args *args) { - grpc_auth_context *auth_context = - grpc_find_auth_context_in_args(args->channel_args); - grpc_server_credentials *creds = - grpc_find_server_credentials_in_args(args->channel_args); - /* grab pointers to our data from the channel element */ - channel_data *chand = elem->channel_data; - - GPR_ASSERT(!args->is_last); - GPR_ASSERT(auth_context != NULL); - GPR_ASSERT(creds != NULL); - - /* initialize members */ - chand->auth_context = - GRPC_AUTH_CONTEXT_REF(auth_context, "server_auth_filter"); - chand->creds = grpc_server_credentials_ref(creds); -} - -/* Destructor for channel data */ -static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, - grpc_channel_element *elem) { - /* grab pointers to our data from the channel element */ - channel_data *chand = elem->channel_data; - GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "server_auth_filter"); - grpc_server_credentials_unref(chand->creds); -} - -const grpc_channel_filter grpc_server_auth_filter = { - auth_start_transport_op, grpc_channel_next_op, sizeof(call_data), - init_call_elem, set_pollset, destroy_call_elem, - sizeof(channel_data), init_channel_elem, destroy_channel_elem, - grpc_call_next_get_peer, "server-auth"}; diff --git a/src/core/lib/security/transport/auth_filters.h b/src/core/lib/security/transport/auth_filters.h new file mode 100644 index 0000000000..f688d4ed21 --- /dev/null +++ b/src/core/lib/security/transport/auth_filters.h @@ -0,0 +1,42 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_AUTH_FILTERS_H +#define GRPC_CORE_LIB_SECURITY_TRANSPORT_AUTH_FILTERS_H + +#include "src/core/lib/channel/channel_stack.h" + +extern const grpc_channel_filter grpc_client_auth_filter; +extern const grpc_channel_filter grpc_server_auth_filter; + +#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_AUTH_FILTERS_H */ diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c new file mode 100644 index 0000000000..e3cbcb4433 --- /dev/null +++ b/src/core/lib/security/transport/client_auth_filter.c @@ -0,0 +1,336 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/transport/auth_filters.h" + +#include + +#include +#include +#include + +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/transport/security_connector.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/call.h" +#include "src/core/lib/transport/static_metadata.h" + +#define MAX_CREDENTIALS_METADATA_COUNT 4 + +/* We can have a per-call credentials. */ +typedef struct { + grpc_call_credentials *creds; + grpc_mdstr *host; + grpc_mdstr *method; + /* pollset bound to this call; if we need to make external + network requests, they should be done under this pollset + so that work can progress when this call wants work to + progress */ + grpc_pollset *pollset; + grpc_transport_stream_op op; + uint8_t security_context_set; + grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT]; + grpc_auth_metadata_context auth_md_context; +} call_data; + +/* We can have a per-channel credentials. */ +typedef struct { + grpc_channel_security_connector *security_connector; + grpc_auth_context *auth_context; +} channel_data; + +static void reset_auth_metadata_context( + grpc_auth_metadata_context *auth_md_context) { + if (auth_md_context->service_url != NULL) { + gpr_free((char *)auth_md_context->service_url); + auth_md_context->service_url = NULL; + } + if (auth_md_context->method_name != NULL) { + gpr_free((char *)auth_md_context->method_name); + auth_md_context->method_name = NULL; + } + GRPC_AUTH_CONTEXT_UNREF( + (grpc_auth_context *)auth_md_context->channel_auth_context, + "grpc_auth_metadata_context"); + auth_md_context->channel_auth_context = NULL; +} + +static void bubble_up_error(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_status_code status, const char *error_msg) { + call_data *calld = elem->call_data; + gpr_log(GPR_ERROR, "Client side authentication failure: %s", error_msg); + grpc_transport_stream_op_add_cancellation(&calld->op, status); + grpc_call_next_op(exec_ctx, elem, &calld->op); +} + +static void on_credentials_metadata(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_credentials_md *md_elems, + size_t num_md, + grpc_credentials_status status) { + grpc_call_element *elem = (grpc_call_element *)user_data; + call_data *calld = elem->call_data; + grpc_transport_stream_op *op = &calld->op; + grpc_metadata_batch *mdb; + size_t i; + reset_auth_metadata_context(&calld->auth_md_context); + if (status != GRPC_CREDENTIALS_OK) { + bubble_up_error(exec_ctx, elem, GRPC_STATUS_UNAUTHENTICATED, + "Credentials failed to get metadata."); + return; + } + GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT); + GPR_ASSERT(op->send_initial_metadata != NULL); + mdb = op->send_initial_metadata; + for (i = 0; i < num_md; i++) { + grpc_metadata_batch_add_tail( + mdb, &calld->md_links[i], + grpc_mdelem_from_slices(gpr_slice_ref(md_elems[i].key), + gpr_slice_ref(md_elems[i].value))); + } + grpc_call_next_op(exec_ctx, elem, op); +} + +void build_auth_metadata_context(grpc_security_connector *sc, + grpc_auth_context *auth_context, + call_data *calld) { + char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method)); + char *last_slash = strrchr(service, '/'); + char *method_name = NULL; + char *service_url = NULL; + reset_auth_metadata_context(&calld->auth_md_context); + if (last_slash == NULL) { + gpr_log(GPR_ERROR, "No '/' found in fully qualified method name"); + service[0] = '\0'; + } else if (last_slash == service) { + /* No service part in fully qualified method name: will just be "/". */ + service[1] = '\0'; + } else { + *last_slash = '\0'; + method_name = gpr_strdup(last_slash + 1); + } + if (method_name == NULL) method_name = gpr_strdup(""); + gpr_asprintf(&service_url, "%s://%s%s", + sc->url_scheme == NULL ? "" : sc->url_scheme, + grpc_mdstr_as_c_string(calld->host), service); + calld->auth_md_context.service_url = service_url; + calld->auth_md_context.method_name = method_name; + calld->auth_md_context.channel_auth_context = + GRPC_AUTH_CONTEXT_REF(auth_context, "grpc_auth_metadata_context"); + gpr_free(service); +} + +static void send_security_metadata(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_transport_stream_op *op) { + call_data *calld = elem->call_data; + channel_data *chand = elem->channel_data; + grpc_client_security_context *ctx = + (grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value; + grpc_call_credentials *channel_call_creds = + chand->security_connector->request_metadata_creds; + int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL); + + if (channel_call_creds == NULL && !call_creds_has_md) { + /* Skip sending metadata altogether. */ + grpc_call_next_op(exec_ctx, elem, op); + return; + } + + if (channel_call_creds != NULL && call_creds_has_md) { + calld->creds = grpc_composite_call_credentials_create(channel_call_creds, + ctx->creds, NULL); + if (calld->creds == NULL) { + bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL, + "Incompatible credentials set on channel and call."); + return; + } + } else { + calld->creds = grpc_call_credentials_ref( + call_creds_has_md ? ctx->creds : channel_call_creds); + } + + build_auth_metadata_context(&chand->security_connector->base, + chand->auth_context, calld); + calld->op = *op; /* Copy op (originates from the caller's stack). */ + GPR_ASSERT(calld->pollset); + grpc_call_credentials_get_request_metadata( + exec_ctx, calld->creds, calld->pollset, calld->auth_md_context, + on_credentials_metadata, elem); +} + +static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_security_status status) { + grpc_call_element *elem = (grpc_call_element *)user_data; + call_data *calld = elem->call_data; + + if (status == GRPC_SECURITY_OK) { + send_security_metadata(exec_ctx, elem, &calld->op); + } else { + char *error_msg; + gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.", + grpc_mdstr_as_c_string(calld->host)); + bubble_up_error(exec_ctx, elem, GRPC_STATUS_INTERNAL, error_msg); + gpr_free(error_msg); + } +} + +/* Called either: + - in response to an API call (or similar) from above, to send something + - a network event (or similar) from below, to receive something + op contains type and call direction information, in addition to the data + that is being sent or received. */ +static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_transport_stream_op *op) { + /* grab pointers to our data from the call element */ + call_data *calld = elem->call_data; + channel_data *chand = elem->channel_data; + grpc_linked_mdelem *l; + grpc_client_security_context *sec_ctx = NULL; + + if (calld->security_context_set == 0 && + op->cancel_with_status == GRPC_STATUS_OK) { + calld->security_context_set = 1; + GPR_ASSERT(op->context); + if (op->context[GRPC_CONTEXT_SECURITY].value == NULL) { + op->context[GRPC_CONTEXT_SECURITY].value = + grpc_client_security_context_create(); + op->context[GRPC_CONTEXT_SECURITY].destroy = + grpc_client_security_context_destroy; + } + sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value; + GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter"); + sec_ctx->auth_context = + GRPC_AUTH_CONTEXT_REF(chand->auth_context, "client_auth_filter"); + } + + if (op->send_initial_metadata != NULL) { + for (l = op->send_initial_metadata->list.head; l != NULL; l = l->next) { + grpc_mdelem *md = l->md; + /* Pointer comparison is OK for md_elems created from the same context. + */ + if (md->key == GRPC_MDSTR_AUTHORITY) { + if (calld->host != NULL) GRPC_MDSTR_UNREF(calld->host); + calld->host = GRPC_MDSTR_REF(md->value); + } else if (md->key == GRPC_MDSTR_PATH) { + if (calld->method != NULL) GRPC_MDSTR_UNREF(calld->method); + calld->method = GRPC_MDSTR_REF(md->value); + } + } + if (calld->host != NULL) { + const char *call_host = grpc_mdstr_as_c_string(calld->host); + calld->op = *op; /* Copy op (originates from the caller's stack). */ + grpc_channel_security_connector_check_call_host( + exec_ctx, chand->security_connector, call_host, chand->auth_context, + on_host_checked, elem); + return; /* early exit */ + } + } + + /* pass control down the stack */ + grpc_call_next_op(exec_ctx, elem, op); +} + +/* Constructor for call_data */ +static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_call_element_args *args) { + call_data *calld = elem->call_data; + memset(calld, 0, sizeof(*calld)); +} + +static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_pollset *pollset) { + call_data *calld = elem->call_data; + calld->pollset = pollset; +} + +/* Destructor for call_data */ +static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + void *ignored) { + call_data *calld = elem->call_data; + grpc_call_credentials_unref(calld->creds); + if (calld->host != NULL) { + GRPC_MDSTR_UNREF(calld->host); + } + if (calld->method != NULL) { + GRPC_MDSTR_UNREF(calld->method); + } + reset_auth_metadata_context(&calld->auth_md_context); +} + +/* Constructor for channel_data */ +static void init_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem, + grpc_channel_element_args *args) { + grpc_security_connector *sc = + grpc_find_security_connector_in_args(args->channel_args); + grpc_auth_context *auth_context = + grpc_find_auth_context_in_args(args->channel_args); + + /* grab pointers to our data from the channel element */ + channel_data *chand = elem->channel_data; + + /* The first and the last filters tend to be implemented differently to + handle the case that there's no 'next' filter to call on the up or down + path */ + GPR_ASSERT(!args->is_last); + GPR_ASSERT(sc != NULL); + GPR_ASSERT(auth_context != NULL); + + /* initialize members */ + chand->security_connector = + (grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF( + sc, "client_auth_filter"); + chand->auth_context = + GRPC_AUTH_CONTEXT_REF(auth_context, "client_auth_filter"); +} + +/* Destructor for channel data */ +static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem) { + /* grab pointers to our data from the channel element */ + channel_data *chand = elem->channel_data; + grpc_channel_security_connector *sc = chand->security_connector; + if (sc != NULL) { + GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "client_auth_filter"); + } + GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "client_auth_filter"); +} + +const grpc_channel_filter grpc_client_auth_filter = { + auth_start_transport_op, grpc_channel_next_op, sizeof(call_data), + init_call_elem, set_pollset, destroy_call_elem, + sizeof(channel_data), init_channel_elem, destroy_channel_elem, + grpc_call_next_get_peer, "client-auth"}; diff --git a/src/core/lib/security/transport/handshake.c b/src/core/lib/security/transport/handshake.c new file mode 100644 index 0000000000..6561f4b47d --- /dev/null +++ b/src/core/lib/security/transport/handshake.c @@ -0,0 +1,336 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/transport/handshake.h" + +#include +#include + +#include +#include +#include +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/transport/secure_endpoint.h" + +#define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256 + +typedef struct { + grpc_security_connector *connector; + tsi_handshaker *handshaker; + bool is_client_side; + unsigned char *handshake_buffer; + size_t handshake_buffer_size; + grpc_endpoint *wrapped_endpoint; + grpc_endpoint *secure_endpoint; + gpr_slice_buffer left_overs; + gpr_slice_buffer incoming; + gpr_slice_buffer outgoing; + grpc_security_handshake_done_cb cb; + void *user_data; + grpc_closure on_handshake_data_sent_to_peer; + grpc_closure on_handshake_data_received_from_peer; + grpc_auth_context *auth_context; +} grpc_security_handshake; + +static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, + void *setup, bool success); + +static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup, + bool success); + +static void security_connector_remove_handshake(grpc_security_handshake *h) { + GPR_ASSERT(!h->is_client_side); + grpc_security_connector_handshake_list *node; + grpc_security_connector_handshake_list *tmp; + grpc_server_security_connector *sc = + (grpc_server_security_connector *)h->connector; + gpr_mu_lock(&sc->mu); + node = sc->handshaking_handshakes; + if (node && node->handshake == h) { + sc->handshaking_handshakes = node->next; + gpr_free(node); + gpr_mu_unlock(&sc->mu); + return; + } + while (node) { + if (node->next->handshake == h) { + tmp = node->next; + node->next = node->next->next; + gpr_free(tmp); + gpr_mu_unlock(&sc->mu); + return; + } + node = node->next; + } + gpr_mu_unlock(&sc->mu); +} + +static void security_handshake_done(grpc_exec_ctx *exec_ctx, + grpc_security_handshake *h, + int is_success) { + if (!h->is_client_side) { + security_connector_remove_handshake(h); + } + if (is_success) { + h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint, + h->auth_context); + } else { + if (h->secure_endpoint != NULL) { + grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint); + grpc_endpoint_destroy(exec_ctx, h->secure_endpoint); + } else { + grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint); + } + h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL, NULL); + } + if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker); + if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer); + gpr_slice_buffer_destroy(&h->left_overs); + gpr_slice_buffer_destroy(&h->outgoing); + gpr_slice_buffer_destroy(&h->incoming); + GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake"); + GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake"); + gpr_free(h); +} + +static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_security_status status, + grpc_auth_context *auth_context) { + grpc_security_handshake *h = user_data; + tsi_frame_protector *protector; + tsi_result result; + if (status != GRPC_SECURITY_OK) { + gpr_log(GPR_ERROR, "Error checking peer."); + security_handshake_done(exec_ctx, h, 0); + return; + } + h->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "handshake"); + result = + tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Frame protector creation failed with error %s.", + tsi_result_to_string(result)); + security_handshake_done(exec_ctx, h, 0); + return; + } + h->secure_endpoint = + grpc_secure_endpoint_create(protector, h->wrapped_endpoint, + h->left_overs.slices, h->left_overs.count); + h->left_overs.count = 0; + h->left_overs.length = 0; + security_handshake_done(exec_ctx, h, 1); + return; +} + +static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) { + tsi_peer peer; + tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer); + + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Peer extraction failed with error %s", + tsi_result_to_string(result)); + security_handshake_done(exec_ctx, h, 0); + return; + } + grpc_security_connector_check_peer(exec_ctx, h->connector, peer, + on_peer_checked, h); +} + +static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx, + grpc_security_handshake *h) { + size_t offset = 0; + tsi_result result = TSI_OK; + gpr_slice to_send; + + do { + size_t to_send_size = h->handshake_buffer_size - offset; + result = tsi_handshaker_get_bytes_to_send_to_peer( + h->handshaker, h->handshake_buffer + offset, &to_send_size); + offset += to_send_size; + if (result == TSI_INCOMPLETE_DATA) { + h->handshake_buffer_size *= 2; + h->handshake_buffer = + gpr_realloc(h->handshake_buffer, h->handshake_buffer_size); + } + } while (result == TSI_INCOMPLETE_DATA); + + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshake failed with error %s", + tsi_result_to_string(result)); + security_handshake_done(exec_ctx, h, 0); + return; + } + + to_send = + gpr_slice_from_copied_buffer((const char *)h->handshake_buffer, offset); + gpr_slice_buffer_reset_and_unref(&h->outgoing); + gpr_slice_buffer_add(&h->outgoing, to_send); + /* TODO(klempner,jboeuf): This should probably use the client setup + deadline */ + grpc_endpoint_write(exec_ctx, h->wrapped_endpoint, &h->outgoing, + &h->on_handshake_data_sent_to_peer); +} + +static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, + void *handshake, + bool success) { + grpc_security_handshake *h = handshake; + size_t consumed_slice_size = 0; + tsi_result result = TSI_OK; + size_t i; + size_t num_left_overs; + int has_left_overs_in_current_slice = 0; + + if (!success) { + gpr_log(GPR_ERROR, "Read failed."); + security_handshake_done(exec_ctx, h, 0); + return; + } + + for (i = 0; i < h->incoming.count; i++) { + consumed_slice_size = GPR_SLICE_LENGTH(h->incoming.slices[i]); + result = tsi_handshaker_process_bytes_from_peer( + h->handshaker, GPR_SLICE_START_PTR(h->incoming.slices[i]), + &consumed_slice_size); + if (!tsi_handshaker_is_in_progress(h->handshaker)) break; + } + + if (tsi_handshaker_is_in_progress(h->handshaker)) { + /* We may need more data. */ + if (result == TSI_INCOMPLETE_DATA) { + grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming, + &h->on_handshake_data_received_from_peer); + return; + } else { + send_handshake_bytes_to_peer(exec_ctx, h); + return; + } + } + + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshake failed with error %s", + tsi_result_to_string(result)); + security_handshake_done(exec_ctx, h, 0); + return; + } + + /* Handshake is done and successful this point. */ + has_left_overs_in_current_slice = + (consumed_slice_size < GPR_SLICE_LENGTH(h->incoming.slices[i])); + num_left_overs = + (has_left_overs_in_current_slice ? 1 : 0) + h->incoming.count - i - 1; + if (num_left_overs == 0) { + check_peer(exec_ctx, h); + return; + } + + /* Put the leftovers in our buffer (ownership transfered). */ + if (has_left_overs_in_current_slice) { + gpr_slice_buffer_add( + &h->left_overs, + gpr_slice_split_tail(&h->incoming.slices[i], consumed_slice_size)); + gpr_slice_unref( + h->incoming.slices[i]); /* split_tail above increments refcount. */ + } + gpr_slice_buffer_addn( + &h->left_overs, &h->incoming.slices[i + 1], + num_left_overs - (size_t)has_left_overs_in_current_slice); + check_peer(exec_ctx, h); +} + +/* If handshake is NULL, the handshake is done. */ +static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, + void *handshake, bool success) { + grpc_security_handshake *h = handshake; + + /* Make sure that write is OK. */ + if (!success) { + gpr_log(GPR_ERROR, "Write failed."); + if (handshake != NULL) security_handshake_done(exec_ctx, h, 0); + return; + } + + /* We may be done. */ + if (tsi_handshaker_is_in_progress(h->handshaker)) { + /* TODO(klempner,jboeuf): This should probably use the client setup + deadline */ + grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming, + &h->on_handshake_data_received_from_peer); + } else { + check_peer(exec_ctx, h); + } +} + +void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx, + tsi_handshaker *handshaker, + grpc_security_connector *connector, + bool is_client_side, + grpc_endpoint *nonsecure_endpoint, + grpc_security_handshake_done_cb cb, + void *user_data) { + grpc_security_connector_handshake_list *handshake_node; + grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake)); + memset(h, 0, sizeof(grpc_security_handshake)); + h->handshaker = handshaker; + h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake"); + h->is_client_side = is_client_side; + h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE; + h->handshake_buffer = gpr_malloc(h->handshake_buffer_size); + h->wrapped_endpoint = nonsecure_endpoint; + h->user_data = user_data; + h->cb = cb; + grpc_closure_init(&h->on_handshake_data_sent_to_peer, + on_handshake_data_sent_to_peer, h); + grpc_closure_init(&h->on_handshake_data_received_from_peer, + on_handshake_data_received_from_peer, h); + gpr_slice_buffer_init(&h->left_overs); + gpr_slice_buffer_init(&h->outgoing); + gpr_slice_buffer_init(&h->incoming); + if (!is_client_side) { + grpc_server_security_connector *server_connector = + (grpc_server_security_connector *)connector; + handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list)); + handshake_node->handshake = h; + gpr_mu_lock(&server_connector->mu); + handshake_node->next = server_connector->handshaking_handshakes; + server_connector->handshaking_handshakes = handshake_node; + gpr_mu_unlock(&server_connector->mu); + } + send_handshake_bytes_to_peer(exec_ctx, h); +} + +void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, + void *handshake) { + grpc_security_handshake *h = handshake; + grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint); +} diff --git a/src/core/lib/security/transport/handshake.h b/src/core/lib/security/transport/handshake.h new file mode 100644 index 0000000000..6ed850b315 --- /dev/null +++ b/src/core/lib/security/transport/handshake.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H +#define GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H + +#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/security/transport/security_connector.h" + +/* Calls the callback upon completion. Takes owership of handshaker. */ +void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx, + tsi_handshaker *handshaker, + grpc_security_connector *connector, + bool is_client_side, + grpc_endpoint *nonsecure_endpoint, + grpc_security_handshake_done_cb cb, + void *user_data); + +void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, void *handshake); + +#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_HANDSHAKE_H */ diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c new file mode 100644 index 0000000000..4438c8e559 --- /dev/null +++ b/src/core/lib/security/transport/secure_endpoint.c @@ -0,0 +1,384 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/transport/secure_endpoint.h" +#include +#include +#include +#include +#include +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/tsi/transport_security_interface.h" + +#define STAGING_BUFFER_SIZE 8192 + +typedef struct { + grpc_endpoint base; + grpc_endpoint *wrapped_ep; + struct tsi_frame_protector *protector; + gpr_mu protector_mu; + /* saved upper level callbacks and user_data. */ + grpc_closure *read_cb; + grpc_closure *write_cb; + grpc_closure on_read; + gpr_slice_buffer *read_buffer; + gpr_slice_buffer source_buffer; + /* saved handshaker leftover data to unprotect. */ + gpr_slice_buffer leftover_bytes; + /* buffers for read and write */ + gpr_slice read_staging_buffer; + + gpr_slice write_staging_buffer; + gpr_slice_buffer output_buffer; + + gpr_refcount ref; +} secure_endpoint; + +int grpc_trace_secure_endpoint = 0; + +static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) { + secure_endpoint *ep = secure_ep; + grpc_endpoint_destroy(exec_ctx, ep->wrapped_ep); + tsi_frame_protector_destroy(ep->protector); + gpr_slice_buffer_destroy(&ep->leftover_bytes); + gpr_slice_unref(ep->read_staging_buffer); + gpr_slice_unref(ep->write_staging_buffer); + gpr_slice_buffer_destroy(&ep->output_buffer); + gpr_slice_buffer_destroy(&ep->source_buffer); + gpr_mu_destroy(&ep->protector_mu); + gpr_free(ep); +} + +/*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/ +#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG +#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \ + secure_endpoint_unref((exec_ctx), (ep), (reason), __FILE__, __LINE__) +#define SECURE_ENDPOINT_REF(ep, reason) \ + secure_endpoint_ref((ep), (reason), __FILE__, __LINE__) +static void secure_endpoint_unref(secure_endpoint *ep, + grpc_closure_list *closure_list, + const char *reason, const char *file, + int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d", + ep, reason, ep->ref.count, ep->ref.count - 1); + if (gpr_unref(&ep->ref)) { + destroy(exec_ctx, ep); + } +} + +static void secure_endpoint_ref(secure_endpoint *ep, const char *reason, + const char *file, int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %d -> %d", + ep, reason, ep->ref.count, ep->ref.count + 1); + gpr_ref(&ep->ref); +} +#else +#define SECURE_ENDPOINT_UNREF(exec_ctx, ep, reason) \ + secure_endpoint_unref((exec_ctx), (ep)) +#define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep)) +static void secure_endpoint_unref(grpc_exec_ctx *exec_ctx, + secure_endpoint *ep) { + if (gpr_unref(&ep->ref)) { + destroy(exec_ctx, ep); + } +} + +static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); } +#endif + +static void flush_read_staging_buffer(secure_endpoint *ep, uint8_t **cur, + uint8_t **end) { + gpr_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer); + ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); + *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer); + *end = GPR_SLICE_END_PTR(ep->read_staging_buffer); +} + +static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep, + bool success) { + if (grpc_trace_secure_endpoint) { + size_t i; + for (i = 0; i < ep->read_buffer->count; i++) { + char *data = gpr_dump_slice(ep->read_buffer->slices[i], + GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "READ %p: %s", ep, data); + gpr_free(data); + } + } + ep->read_buffer = NULL; + grpc_exec_ctx_enqueue(exec_ctx, ep->read_cb, success, NULL); + SECURE_ENDPOINT_UNREF(exec_ctx, ep, "read"); +} + +static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success) { + unsigned i; + uint8_t keep_looping = 0; + tsi_result result = TSI_OK; + secure_endpoint *ep = (secure_endpoint *)user_data; + uint8_t *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer); + uint8_t *end = GPR_SLICE_END_PTR(ep->read_staging_buffer); + + if (!success) { + gpr_slice_buffer_reset_and_unref(ep->read_buffer); + call_read_cb(exec_ctx, ep, 0); + return; + } + + /* TODO(yangg) check error, maybe bail out early */ + for (i = 0; i < ep->source_buffer.count; i++) { + gpr_slice encrypted = ep->source_buffer.slices[i]; + uint8_t *message_bytes = GPR_SLICE_START_PTR(encrypted); + size_t message_size = GPR_SLICE_LENGTH(encrypted); + + while (message_size > 0 || keep_looping) { + size_t unprotected_buffer_size_written = (size_t)(end - cur); + size_t processed_message_size = message_size; + gpr_mu_lock(&ep->protector_mu); + result = tsi_frame_protector_unprotect(ep->protector, message_bytes, + &processed_message_size, cur, + &unprotected_buffer_size_written); + gpr_mu_unlock(&ep->protector_mu); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Decryption error: %s", + tsi_result_to_string(result)); + break; + } + message_bytes += processed_message_size; + message_size -= processed_message_size; + cur += unprotected_buffer_size_written; + + if (cur == end) { + flush_read_staging_buffer(ep, &cur, &end); + /* Force to enter the loop again to extract buffered bytes in protector. + The bytes could be buffered because of running out of staging_buffer. + If this happens at the end of all slices, doing another unprotect + avoids leaving data in the protector. */ + keep_looping = 1; + } else if (unprotected_buffer_size_written > 0) { + keep_looping = 1; + } else { + keep_looping = 0; + } + } + if (result != TSI_OK) break; + } + + if (cur != GPR_SLICE_START_PTR(ep->read_staging_buffer)) { + gpr_slice_buffer_add( + ep->read_buffer, + gpr_slice_split_head( + &ep->read_staging_buffer, + (size_t)(cur - GPR_SLICE_START_PTR(ep->read_staging_buffer)))); + } + + /* TODO(yangg) experiment with moving this block after read_cb to see if it + helps latency */ + gpr_slice_buffer_reset_and_unref(&ep->source_buffer); + + if (result != TSI_OK) { + gpr_slice_buffer_reset_and_unref(ep->read_buffer); + call_read_cb(exec_ctx, ep, 0); + return; + } + + call_read_cb(exec_ctx, ep, 1); +} + +static void endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, + gpr_slice_buffer *slices, grpc_closure *cb) { + secure_endpoint *ep = (secure_endpoint *)secure_ep; + ep->read_cb = cb; + ep->read_buffer = slices; + gpr_slice_buffer_reset_and_unref(ep->read_buffer); + + SECURE_ENDPOINT_REF(ep, "read"); + if (ep->leftover_bytes.count) { + gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer); + GPR_ASSERT(ep->leftover_bytes.count == 0); + on_read(exec_ctx, ep, 1); + return; + } + + grpc_endpoint_read(exec_ctx, ep->wrapped_ep, &ep->source_buffer, + &ep->on_read); +} + +static void flush_write_staging_buffer(secure_endpoint *ep, uint8_t **cur, + uint8_t **end) { + gpr_slice_buffer_add(&ep->output_buffer, ep->write_staging_buffer); + ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); + *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer); + *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); +} + +static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, + gpr_slice_buffer *slices, grpc_closure *cb) { + unsigned i; + tsi_result result = TSI_OK; + secure_endpoint *ep = (secure_endpoint *)secure_ep; + uint8_t *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer); + uint8_t *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); + + gpr_slice_buffer_reset_and_unref(&ep->output_buffer); + + if (grpc_trace_secure_endpoint) { + for (i = 0; i < slices->count; i++) { + char *data = + gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data); + gpr_free(data); + } + } + + for (i = 0; i < slices->count; i++) { + gpr_slice plain = slices->slices[i]; + uint8_t *message_bytes = GPR_SLICE_START_PTR(plain); + size_t message_size = GPR_SLICE_LENGTH(plain); + while (message_size > 0) { + size_t protected_buffer_size_to_send = (size_t)(end - cur); + size_t processed_message_size = message_size; + gpr_mu_lock(&ep->protector_mu); + result = tsi_frame_protector_protect(ep->protector, message_bytes, + &processed_message_size, cur, + &protected_buffer_size_to_send); + gpr_mu_unlock(&ep->protector_mu); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Encryption error: %s", + tsi_result_to_string(result)); + break; + } + message_bytes += processed_message_size; + message_size -= processed_message_size; + cur += protected_buffer_size_to_send; + + if (cur == end) { + flush_write_staging_buffer(ep, &cur, &end); + } + } + if (result != TSI_OK) break; + } + if (result == TSI_OK) { + size_t still_pending_size; + do { + size_t protected_buffer_size_to_send = (size_t)(end - cur); + gpr_mu_lock(&ep->protector_mu); + result = tsi_frame_protector_protect_flush(ep->protector, cur, + &protected_buffer_size_to_send, + &still_pending_size); + gpr_mu_unlock(&ep->protector_mu); + if (result != TSI_OK) break; + cur += protected_buffer_size_to_send; + if (cur == end) { + flush_write_staging_buffer(ep, &cur, &end); + } + } while (still_pending_size > 0); + if (cur != GPR_SLICE_START_PTR(ep->write_staging_buffer)) { + gpr_slice_buffer_add( + &ep->output_buffer, + gpr_slice_split_head( + &ep->write_staging_buffer, + (size_t)(cur - GPR_SLICE_START_PTR(ep->write_staging_buffer)))); + } + } + + if (result != TSI_OK) { + /* TODO(yangg) do different things according to the error type? */ + gpr_slice_buffer_reset_and_unref(&ep->output_buffer); + grpc_exec_ctx_enqueue(exec_ctx, cb, false, NULL); + return; + } + + grpc_endpoint_write(exec_ctx, ep->wrapped_ep, &ep->output_buffer, cb); +} + +static void endpoint_shutdown(grpc_exec_ctx *exec_ctx, + grpc_endpoint *secure_ep) { + secure_endpoint *ep = (secure_endpoint *)secure_ep; + grpc_endpoint_shutdown(exec_ctx, ep->wrapped_ep); +} + +static void endpoint_destroy(grpc_exec_ctx *exec_ctx, + grpc_endpoint *secure_ep) { + secure_endpoint *ep = (secure_endpoint *)secure_ep; + SECURE_ENDPOINT_UNREF(exec_ctx, ep, "destroy"); +} + +static void endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx, + grpc_endpoint *secure_ep, + grpc_pollset *pollset) { + secure_endpoint *ep = (secure_endpoint *)secure_ep; + grpc_endpoint_add_to_pollset(exec_ctx, ep->wrapped_ep, pollset); +} + +static void endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_endpoint *secure_ep, + grpc_pollset_set *pollset_set) { + secure_endpoint *ep = (secure_endpoint *)secure_ep; + grpc_endpoint_add_to_pollset_set(exec_ctx, ep->wrapped_ep, pollset_set); +} + +static char *endpoint_get_peer(grpc_endpoint *secure_ep) { + secure_endpoint *ep = (secure_endpoint *)secure_ep; + return grpc_endpoint_get_peer(ep->wrapped_ep); +} + +static const grpc_endpoint_vtable vtable = { + endpoint_read, endpoint_write, + endpoint_add_to_pollset, endpoint_add_to_pollset_set, + endpoint_shutdown, endpoint_destroy, + endpoint_get_peer}; + +grpc_endpoint *grpc_secure_endpoint_create( + struct tsi_frame_protector *protector, grpc_endpoint *transport, + gpr_slice *leftover_slices, size_t leftover_nslices) { + size_t i; + secure_endpoint *ep = (secure_endpoint *)gpr_malloc(sizeof(secure_endpoint)); + ep->base.vtable = &vtable; + ep->wrapped_ep = transport; + ep->protector = protector; + gpr_slice_buffer_init(&ep->leftover_bytes); + for (i = 0; i < leftover_nslices; i++) { + gpr_slice_buffer_add(&ep->leftover_bytes, + gpr_slice_ref(leftover_slices[i])); + } + ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); + ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); + gpr_slice_buffer_init(&ep->output_buffer); + gpr_slice_buffer_init(&ep->source_buffer); + ep->read_buffer = NULL; + grpc_closure_init(&ep->on_read, on_read, ep); + gpr_mu_init(&ep->protector_mu); + gpr_ref_init(&ep->ref, 1); + return &ep->base; +} diff --git a/src/core/lib/security/transport/secure_endpoint.h b/src/core/lib/security/transport/secure_endpoint.h new file mode 100644 index 0000000000..d00075b769 --- /dev/null +++ b/src/core/lib/security/transport/secure_endpoint.h @@ -0,0 +1,49 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURE_ENDPOINT_H +#define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURE_ENDPOINT_H + +#include +#include "src/core/lib/iomgr/endpoint.h" + +struct tsi_frame_protector; + +extern int grpc_trace_secure_endpoint; + +/* Takes ownership of protector and to_wrap, and refs leftover_slices. */ +grpc_endpoint *grpc_secure_endpoint_create( + struct tsi_frame_protector *protector, grpc_endpoint *to_wrap, + gpr_slice *leftover_slices, size_t leftover_nslices); + +#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURE_ENDPOINT_H */ diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c new file mode 100644 index 0000000000..72173e7c9d --- /dev/null +++ b/src/core/lib/security/transport/security_connector.c @@ -0,0 +1,838 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/transport/security_connector.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "src/core/ext/transport/chttp2/alpn/alpn.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/transport/handshake.h" +#include "src/core/lib/security/transport/secure_endpoint.h" +#include "src/core/lib/support/env.h" +#include "src/core/lib/support/load_file.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/tsi/fake_transport_security.h" +#include "src/core/lib/tsi/ssl_transport_security.h" + +/* -- Constants. -- */ + +#ifndef INSTALL_PREFIX +static const char *installed_roots_path = "/usr/share/grpc/roots.pem"; +#else +static const char *installed_roots_path = + INSTALL_PREFIX "/share/grpc/roots.pem"; +#endif + +/* -- Overridden default roots. -- */ + +static grpc_ssl_roots_override_callback ssl_roots_override_cb = NULL; + +void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb) { + ssl_roots_override_cb = cb; +} + +/* -- Cipher suites. -- */ + +/* Defines the cipher suites that we accept by default. All these cipher suites + are compliant with HTTP2. */ +#define GRPC_SSL_CIPHER_SUITES \ + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" \ + "SHA384:ECDHE-RSA-AES256-GCM-SHA384" + +static gpr_once cipher_suites_once = GPR_ONCE_INIT; +static const char *cipher_suites = NULL; + +static void init_cipher_suites(void) { + char *overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES"); + cipher_suites = overridden != NULL ? overridden : GRPC_SSL_CIPHER_SUITES; +} + +static const char *ssl_cipher_suites(void) { + gpr_once_init(&cipher_suites_once, init_cipher_suites); + return cipher_suites; +} + +/* -- Common methods. -- */ + +/* Returns the first property with that name. */ +const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer, + const char *name) { + size_t i; + if (peer == NULL) return NULL; + for (i = 0; i < peer->property_count; i++) { + const tsi_peer_property *property = &peer->properties[i]; + if (name == NULL && property->name == NULL) { + return property; + } + if (name != NULL && property->name != NULL && + strcmp(property->name, name) == 0) { + return property; + } + } + return NULL; +} + +void grpc_server_security_connector_shutdown( + grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector) { + grpc_security_connector_handshake_list *tmp; + gpr_mu_lock(&connector->mu); + while (connector->handshaking_handshakes) { + tmp = connector->handshaking_handshakes; + grpc_security_handshake_shutdown( + exec_ctx, connector->handshaking_handshakes->handshake); + connector->handshaking_handshakes = tmp->next; + gpr_free(tmp); + } + gpr_mu_unlock(&connector->mu); +} + +void grpc_channel_security_connector_do_handshake( + grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, + grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb, + void *user_data) { + if (sc == NULL || nonsecure_endpoint == NULL) { + cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL); + } else { + sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data); + } +} + +void grpc_server_security_connector_do_handshake( + grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, + grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint, + grpc_security_handshake_done_cb cb, void *user_data) { + if (sc == NULL || nonsecure_endpoint == NULL) { + cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL); + } else { + sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, cb, user_data); + } +} + +void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx, + grpc_security_connector *sc, + tsi_peer peer, + grpc_security_peer_check_cb cb, + void *user_data) { + if (sc == NULL) { + cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL); + tsi_peer_destruct(&peer); + } else { + sc->vtable->check_peer(exec_ctx, sc, peer, cb, user_data); + } +} + +void grpc_channel_security_connector_check_call_host( + grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, + const char *host, grpc_auth_context *auth_context, + grpc_security_call_host_check_cb cb, void *user_data) { + if (sc == NULL || sc->check_call_host == NULL) { + cb(exec_ctx, user_data, GRPC_SECURITY_ERROR); + } else { + sc->check_call_host(exec_ctx, sc, host, auth_context, cb, user_data); + } +} + +#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG +grpc_security_connector *grpc_security_connector_ref( + grpc_security_connector *sc, const char *file, int line, + const char *reason) { + if (sc == NULL) return NULL; + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "SECURITY_CONNECTOR:%p ref %d -> %d %s", sc, + (int)sc->refcount.count, (int)sc->refcount.count + 1, reason); +#else +grpc_security_connector *grpc_security_connector_ref( + grpc_security_connector *sc) { + if (sc == NULL) return NULL; +#endif + gpr_ref(&sc->refcount); + return sc; +} + +#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG +void grpc_security_connector_unref(grpc_security_connector *sc, + const char *file, int line, + const char *reason) { + if (sc == NULL) return; + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "SECURITY_CONNECTOR:%p unref %d -> %d %s", sc, + (int)sc->refcount.count, (int)sc->refcount.count - 1, reason); +#else +void grpc_security_connector_unref(grpc_security_connector *sc) { + if (sc == NULL) return; +#endif + if (gpr_unref(&sc->refcount)) sc->vtable->destroy(sc); +} + +static void connector_pointer_arg_destroy(void *p) { + GRPC_SECURITY_CONNECTOR_UNREF(p, "connector_pointer_arg"); +} + +static void *connector_pointer_arg_copy(void *p) { + return GRPC_SECURITY_CONNECTOR_REF(p, "connector_pointer_arg"); +} + +static int connector_pointer_cmp(void *a, void *b) { return GPR_ICMP(a, b); } + +static const grpc_arg_pointer_vtable connector_pointer_vtable = { + connector_pointer_arg_copy, connector_pointer_arg_destroy, + connector_pointer_cmp}; + +grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc) { + grpc_arg result; + result.type = GRPC_ARG_POINTER; + result.key = GRPC_SECURITY_CONNECTOR_ARG; + result.value.pointer.vtable = &connector_pointer_vtable; + result.value.pointer.p = sc; + return result; +} + +grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg) { + if (strcmp(arg->key, GRPC_SECURITY_CONNECTOR_ARG)) return NULL; + if (arg->type != GRPC_ARG_POINTER) { + gpr_log(GPR_ERROR, "Invalid type %d for arg %s", arg->type, + GRPC_SECURITY_CONNECTOR_ARG); + return NULL; + } + return arg->value.pointer.p; +} + +grpc_security_connector *grpc_find_security_connector_in_args( + const grpc_channel_args *args) { + size_t i; + if (args == NULL) return NULL; + for (i = 0; i < args->num_args; i++) { + grpc_security_connector *sc = + grpc_security_connector_from_arg(&args->args[i]); + if (sc != NULL) return sc; + } + return NULL; +} + +/* -- Fake implementation. -- */ + +static void fake_channel_destroy(grpc_security_connector *sc) { + grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc; + grpc_call_credentials_unref(c->request_metadata_creds); + gpr_free(sc); +} + +static void fake_server_destroy(grpc_security_connector *sc) { + grpc_server_security_connector *c = (grpc_server_security_connector *)sc; + gpr_mu_destroy(&c->mu); + gpr_free(sc); +} + +static void fake_check_peer(grpc_exec_ctx *exec_ctx, + grpc_security_connector *sc, tsi_peer peer, + grpc_security_peer_check_cb cb, void *user_data) { + const char *prop_name; + grpc_security_status status = GRPC_SECURITY_OK; + grpc_auth_context *auth_context = NULL; + if (peer.property_count != 1) { + gpr_log(GPR_ERROR, "Fake peers should only have 1 property."); + status = GRPC_SECURITY_ERROR; + goto end; + } + prop_name = peer.properties[0].name; + if (prop_name == NULL || + strcmp(prop_name, TSI_CERTIFICATE_TYPE_PEER_PROPERTY)) { + gpr_log(GPR_ERROR, "Unexpected property in fake peer: %s.", + prop_name == NULL ? "" : prop_name); + status = GRPC_SECURITY_ERROR; + goto end; + } + if (strncmp(peer.properties[0].value.data, TSI_FAKE_CERTIFICATE_TYPE, + peer.properties[0].value.length)) { + gpr_log(GPR_ERROR, "Invalid value for cert type property."); + status = GRPC_SECURITY_ERROR; + goto end; + } + auth_context = grpc_auth_context_create(NULL); + grpc_auth_context_add_cstring_property( + auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_FAKE_TRANSPORT_SECURITY_TYPE); + +end: + cb(exec_ctx, user_data, status, auth_context); + grpc_auth_context_unref(auth_context); + tsi_peer_destruct(&peer); +} + +static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx, + grpc_channel_security_connector *sc, + const char *host, + grpc_auth_context *auth_context, + grpc_security_call_host_check_cb cb, + void *user_data) { + cb(exec_ctx, user_data, GRPC_SECURITY_OK); +} + +static void fake_channel_do_handshake(grpc_exec_ctx *exec_ctx, + grpc_channel_security_connector *sc, + grpc_endpoint *nonsecure_endpoint, + grpc_security_handshake_done_cb cb, + void *user_data) { + grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), &sc->base, + true, nonsecure_endpoint, cb, user_data); +} + +static void fake_server_do_handshake(grpc_exec_ctx *exec_ctx, + grpc_server_security_connector *sc, + grpc_tcp_server_acceptor *acceptor, + grpc_endpoint *nonsecure_endpoint, + grpc_security_handshake_done_cb cb, + void *user_data) { + grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), &sc->base, + false, nonsecure_endpoint, cb, user_data); +} + +static grpc_security_connector_vtable fake_channel_vtable = { + fake_channel_destroy, fake_check_peer}; + +static grpc_security_connector_vtable fake_server_vtable = {fake_server_destroy, + fake_check_peer}; + +grpc_channel_security_connector *grpc_fake_channel_security_connector_create( + grpc_call_credentials *request_metadata_creds) { + grpc_channel_security_connector *c = gpr_malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + gpr_ref_init(&c->base.refcount, 1); + c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; + c->base.vtable = &fake_channel_vtable; + c->request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds); + c->check_call_host = fake_channel_check_call_host; + c->do_handshake = fake_channel_do_handshake; + return c; +} + +grpc_server_security_connector *grpc_fake_server_security_connector_create( + void) { + grpc_server_security_connector *c = + gpr_malloc(sizeof(grpc_server_security_connector)); + memset(c, 0, sizeof(*c)); + gpr_ref_init(&c->base.refcount, 1); + c->base.vtable = &fake_server_vtable; + c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME; + c->do_handshake = fake_server_do_handshake; + gpr_mu_init(&c->mu); + return c; +} + +/* --- Ssl implementation. --- */ + +typedef struct { + grpc_channel_security_connector base; + tsi_ssl_handshaker_factory *handshaker_factory; + char *target_name; + char *overridden_target_name; +} grpc_ssl_channel_security_connector; + +typedef struct { + grpc_server_security_connector base; + tsi_ssl_handshaker_factory *handshaker_factory; +} grpc_ssl_server_security_connector; + +static void ssl_channel_destroy(grpc_security_connector *sc) { + grpc_ssl_channel_security_connector *c = + (grpc_ssl_channel_security_connector *)sc; + grpc_call_credentials_unref(c->base.request_metadata_creds); + if (c->handshaker_factory != NULL) { + tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); + } + if (c->target_name != NULL) gpr_free(c->target_name); + if (c->overridden_target_name != NULL) gpr_free(c->overridden_target_name); + gpr_free(sc); +} + +static void ssl_server_destroy(grpc_security_connector *sc) { + grpc_ssl_server_security_connector *c = + (grpc_ssl_server_security_connector *)sc; + + if (c->handshaker_factory != NULL) { + tsi_ssl_handshaker_factory_destroy(c->handshaker_factory); + } + gpr_mu_destroy(&c->base.mu); + gpr_free(sc); +} + +static grpc_security_status ssl_create_handshaker( + tsi_ssl_handshaker_factory *handshaker_factory, bool is_client, + const char *peer_name, tsi_handshaker **handshaker) { + tsi_result result = TSI_OK; + if (handshaker_factory == NULL) return GRPC_SECURITY_ERROR; + result = tsi_ssl_handshaker_factory_create_handshaker( + handshaker_factory, is_client ? peer_name : NULL, handshaker); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.", + tsi_result_to_string(result)); + return GRPC_SECURITY_ERROR; + } + return GRPC_SECURITY_OK; +} + +static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx, + grpc_channel_security_connector *sc, + grpc_endpoint *nonsecure_endpoint, + grpc_security_handshake_done_cb cb, + void *user_data) { + grpc_ssl_channel_security_connector *c = + (grpc_ssl_channel_security_connector *)sc; + tsi_handshaker *handshaker; + grpc_security_status status = ssl_create_handshaker( + c->handshaker_factory, true, + c->overridden_target_name != NULL ? c->overridden_target_name + : c->target_name, + &handshaker); + if (status != GRPC_SECURITY_OK) { + cb(exec_ctx, user_data, status, NULL, NULL); + } else { + grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true, + nonsecure_endpoint, cb, user_data); + } +} + +static void ssl_server_do_handshake(grpc_exec_ctx *exec_ctx, + grpc_server_security_connector *sc, + grpc_tcp_server_acceptor *acceptor, + grpc_endpoint *nonsecure_endpoint, + grpc_security_handshake_done_cb cb, + void *user_data) { + grpc_ssl_server_security_connector *c = + (grpc_ssl_server_security_connector *)sc; + tsi_handshaker *handshaker; + grpc_security_status status = + ssl_create_handshaker(c->handshaker_factory, false, NULL, &handshaker); + if (status != GRPC_SECURITY_OK) { + cb(exec_ctx, user_data, status, NULL, NULL); + } else { + grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, false, + nonsecure_endpoint, cb, user_data); + } +} + +static int ssl_host_matches_name(const tsi_peer *peer, const char *peer_name) { + char *allocated_name = NULL; + int r; + + if (strchr(peer_name, ':') != NULL) { + char *ignored_port; + gpr_split_host_port(peer_name, &allocated_name, &ignored_port); + gpr_free(ignored_port); + peer_name = allocated_name; + if (!peer_name) return 0; + } + r = tsi_ssl_peer_matches_name(peer, peer_name); + gpr_free(allocated_name); + return r; +} + +grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer) { + size_t i; + grpc_auth_context *ctx = NULL; + const char *peer_identity_property_name = NULL; + + /* The caller has checked the certificate type property. */ + GPR_ASSERT(peer->property_count >= 1); + ctx = grpc_auth_context_create(NULL); + grpc_auth_context_add_cstring_property( + ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_SSL_TRANSPORT_SECURITY_TYPE); + for (i = 0; i < peer->property_count; i++) { + const tsi_peer_property *prop = &peer->properties[i]; + if (prop->name == NULL) continue; + if (strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) { + /* If there is no subject alt name, have the CN as the identity. */ + if (peer_identity_property_name == NULL) { + peer_identity_property_name = GRPC_X509_CN_PROPERTY_NAME; + } + grpc_auth_context_add_property(ctx, GRPC_X509_CN_PROPERTY_NAME, + prop->value.data, prop->value.length); + } else if (strcmp(prop->name, + TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) { + peer_identity_property_name = GRPC_X509_SAN_PROPERTY_NAME; + grpc_auth_context_add_property(ctx, GRPC_X509_SAN_PROPERTY_NAME, + prop->value.data, prop->value.length); + } else if (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0) { + grpc_auth_context_add_property(ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME, + prop->value.data, prop->value.length); + } + } + if (peer_identity_property_name != NULL) { + GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name( + ctx, peer_identity_property_name) == 1); + } + return ctx; +} + +static grpc_security_status ssl_check_peer(grpc_security_connector *sc, + const char *peer_name, + const tsi_peer *peer, + grpc_auth_context **auth_context) { + /* Check the ALPN. */ + const tsi_peer_property *p = + tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); + if (p == NULL) { + gpr_log(GPR_ERROR, "Missing selected ALPN property."); + return GRPC_SECURITY_ERROR; + } + if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) { + gpr_log(GPR_ERROR, "Invalid ALPN value."); + return GRPC_SECURITY_ERROR; + } + + /* Check the peer name if specified. */ + if (peer_name != NULL && !ssl_host_matches_name(peer, peer_name)) { + gpr_log(GPR_ERROR, "Peer name %s is not in peer certificate", peer_name); + return GRPC_SECURITY_ERROR; + } + *auth_context = tsi_ssl_peer_to_auth_context(peer); + return GRPC_SECURITY_OK; +} + +static void ssl_channel_check_peer(grpc_exec_ctx *exec_ctx, + grpc_security_connector *sc, tsi_peer peer, + grpc_security_peer_check_cb cb, + void *user_data) { + grpc_ssl_channel_security_connector *c = + (grpc_ssl_channel_security_connector *)sc; + grpc_security_status status; + grpc_auth_context *auth_context = NULL; + status = ssl_check_peer(sc, c->overridden_target_name != NULL + ? c->overridden_target_name + : c->target_name, + &peer, &auth_context); + cb(exec_ctx, user_data, status, auth_context); + grpc_auth_context_unref(auth_context); + tsi_peer_destruct(&peer); +} + +static void ssl_server_check_peer(grpc_exec_ctx *exec_ctx, + grpc_security_connector *sc, tsi_peer peer, + grpc_security_peer_check_cb cb, + void *user_data) { + grpc_auth_context *auth_context = NULL; + grpc_security_status status = ssl_check_peer(sc, NULL, &peer, &auth_context); + tsi_peer_destruct(&peer); + cb(exec_ctx, user_data, status, auth_context); + grpc_auth_context_unref(auth_context); +} + +static void add_shallow_auth_property_to_peer(tsi_peer *peer, + const grpc_auth_property *prop, + const char *tsi_prop_name) { + tsi_peer_property *tsi_prop = &peer->properties[peer->property_count++]; + tsi_prop->name = (char *)tsi_prop_name; + tsi_prop->value.data = prop->value; + tsi_prop->value.length = prop->value_length; +} + +tsi_peer tsi_shallow_peer_from_ssl_auth_context( + const grpc_auth_context *auth_context) { + size_t max_num_props = 0; + grpc_auth_property_iterator it; + const grpc_auth_property *prop; + tsi_peer peer; + memset(&peer, 0, sizeof(peer)); + + it = grpc_auth_context_property_iterator(auth_context); + while (grpc_auth_property_iterator_next(&it) != NULL) max_num_props++; + + if (max_num_props > 0) { + peer.properties = gpr_malloc(max_num_props * sizeof(tsi_peer_property)); + it = grpc_auth_context_property_iterator(auth_context); + while ((prop = grpc_auth_property_iterator_next(&it)) != NULL) { + if (strcmp(prop->name, GRPC_X509_SAN_PROPERTY_NAME) == 0) { + add_shallow_auth_property_to_peer( + &peer, prop, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY); + } else if (strcmp(prop->name, GRPC_X509_CN_PROPERTY_NAME) == 0) { + add_shallow_auth_property_to_peer( + &peer, prop, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY); + } else if (strcmp(prop->name, GRPC_X509_PEM_CERT_PROPERTY_NAME) == 0) { + add_shallow_auth_property_to_peer(&peer, prop, + TSI_X509_PEM_CERT_PROPERTY); + } + } + } + return peer; +} + +void tsi_shallow_peer_destruct(tsi_peer *peer) { + if (peer->properties != NULL) gpr_free(peer->properties); +} + +static void ssl_channel_check_call_host(grpc_exec_ctx *exec_ctx, + grpc_channel_security_connector *sc, + const char *host, + grpc_auth_context *auth_context, + grpc_security_call_host_check_cb cb, + void *user_data) { + grpc_ssl_channel_security_connector *c = + (grpc_ssl_channel_security_connector *)sc; + grpc_security_status status = GRPC_SECURITY_ERROR; + tsi_peer peer = tsi_shallow_peer_from_ssl_auth_context(auth_context); + if (ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK; + + /* If the target name was overridden, then the original target_name was + 'checked' transitively during the previous peer check at the end of the + handshake. */ + if (c->overridden_target_name != NULL && strcmp(host, c->target_name) == 0) { + status = GRPC_SECURITY_OK; + } + cb(exec_ctx, user_data, status); + tsi_shallow_peer_destruct(&peer); +} + +static grpc_security_connector_vtable ssl_channel_vtable = { + ssl_channel_destroy, ssl_channel_check_peer}; + +static grpc_security_connector_vtable ssl_server_vtable = { + ssl_server_destroy, ssl_server_check_peer}; + +static gpr_slice compute_default_pem_root_certs_once(void) { + gpr_slice result = gpr_empty_slice(); + + /* First try to load the roots from the environment. */ + char *default_root_certs_path = + gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); + if (default_root_certs_path != NULL) { + result = gpr_load_file(default_root_certs_path, 0, NULL); + gpr_free(default_root_certs_path); + } + + /* Try overridden roots if needed. */ + grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL; + if (GPR_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != NULL) { + char *pem_root_certs = NULL; + ovrd_res = ssl_roots_override_cb(&pem_root_certs); + if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) { + GPR_ASSERT(pem_root_certs != NULL); + result = gpr_slice_new(pem_root_certs, strlen(pem_root_certs), gpr_free); + } + } + + /* Fall back to installed certs if needed. */ + if (GPR_SLICE_IS_EMPTY(result) && + ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { + result = gpr_load_file(installed_roots_path, 0, NULL); + } + return result; +} + +static gpr_slice default_pem_root_certs; + +static void init_default_pem_root_certs(void) { + default_pem_root_certs = compute_default_pem_root_certs_once(); +} + +gpr_slice grpc_get_default_ssl_roots_for_testing(void) { + return compute_default_pem_root_certs_once(); +} + +static tsi_client_certificate_request_type +get_tsi_client_certificate_request_type( + grpc_ssl_client_certificate_request_type grpc_request_type) { + switch (grpc_request_type) { + case GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE: + return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; + + case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: + return TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; + + case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY: + return TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY; + + case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY: + return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY; + + case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY: + return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY; + + default: + // Is this a sane default + return TSI_DONT_REQUEST_CLIENT_CERTIFICATE; + } +} + +size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) { + /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in + loading all the roots once for the lifetime of the process. */ + static gpr_once once = GPR_ONCE_INIT; + gpr_once_init(&once, init_default_pem_root_certs); + *pem_root_certs = GPR_SLICE_START_PTR(default_pem_root_certs); + return GPR_SLICE_LENGTH(default_pem_root_certs); +} + +grpc_security_status grpc_ssl_channel_security_connector_create( + grpc_call_credentials *request_metadata_creds, + const grpc_ssl_config *config, const char *target_name, + const char *overridden_target_name, grpc_channel_security_connector **sc) { + size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions(); + const unsigned char **alpn_protocol_strings = + gpr_malloc(sizeof(const char *) * num_alpn_protocols); + unsigned char *alpn_protocol_string_lengths = + gpr_malloc(sizeof(unsigned char) * num_alpn_protocols); + tsi_result result = TSI_OK; + grpc_ssl_channel_security_connector *c; + size_t i; + const unsigned char *pem_root_certs; + size_t pem_root_certs_size; + char *port; + + for (i = 0; i < num_alpn_protocols; i++) { + alpn_protocol_strings[i] = + (const unsigned char *)grpc_chttp2_get_alpn_version_index(i); + alpn_protocol_string_lengths[i] = + (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i)); + } + + if (config == NULL || target_name == NULL) { + gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name."); + goto error; + } + if (config->pem_root_certs == NULL) { + pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs); + if (pem_root_certs == NULL || pem_root_certs_size == 0) { + gpr_log(GPR_ERROR, "Could not get default pem root certs."); + goto error; + } + } else { + pem_root_certs = config->pem_root_certs; + pem_root_certs_size = config->pem_root_certs_size; + } + + c = gpr_malloc(sizeof(grpc_ssl_channel_security_connector)); + memset(c, 0, sizeof(grpc_ssl_channel_security_connector)); + + gpr_ref_init(&c->base.base.refcount, 1); + c->base.base.vtable = &ssl_channel_vtable; + c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; + c->base.request_metadata_creds = + grpc_call_credentials_ref(request_metadata_creds); + c->base.check_call_host = ssl_channel_check_call_host; + c->base.do_handshake = ssl_channel_do_handshake; + gpr_split_host_port(target_name, &c->target_name, &port); + gpr_free(port); + if (overridden_target_name != NULL) { + c->overridden_target_name = gpr_strdup(overridden_target_name); + } + result = tsi_create_ssl_client_handshaker_factory( + config->pem_private_key, config->pem_private_key_size, + config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs, + pem_root_certs_size, ssl_cipher_suites(), alpn_protocol_strings, + alpn_protocol_string_lengths, (uint16_t)num_alpn_protocols, + &c->handshaker_factory); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", + tsi_result_to_string(result)); + ssl_channel_destroy(&c->base.base); + *sc = NULL; + goto error; + } + *sc = &c->base; + gpr_free((void *)alpn_protocol_strings); + gpr_free(alpn_protocol_string_lengths); + return GRPC_SECURITY_OK; + +error: + gpr_free((void *)alpn_protocol_strings); + gpr_free(alpn_protocol_string_lengths); + return GRPC_SECURITY_ERROR; +} + +grpc_security_status grpc_ssl_server_security_connector_create( + const grpc_ssl_server_config *config, grpc_server_security_connector **sc) { + size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions(); + const unsigned char **alpn_protocol_strings = + gpr_malloc(sizeof(const char *) * num_alpn_protocols); + unsigned char *alpn_protocol_string_lengths = + gpr_malloc(sizeof(unsigned char) * num_alpn_protocols); + tsi_result result = TSI_OK; + grpc_ssl_server_security_connector *c; + size_t i; + + for (i = 0; i < num_alpn_protocols; i++) { + alpn_protocol_strings[i] = + (const unsigned char *)grpc_chttp2_get_alpn_version_index(i); + alpn_protocol_string_lengths[i] = + (unsigned char)strlen(grpc_chttp2_get_alpn_version_index(i)); + } + + if (config == NULL || config->num_key_cert_pairs == 0) { + gpr_log(GPR_ERROR, "An SSL server needs a key and a cert."); + goto error; + } + c = gpr_malloc(sizeof(grpc_ssl_server_security_connector)); + memset(c, 0, sizeof(grpc_ssl_server_security_connector)); + + gpr_ref_init(&c->base.base.refcount, 1); + c->base.base.url_scheme = GRPC_SSL_URL_SCHEME; + c->base.base.vtable = &ssl_server_vtable; + result = tsi_create_ssl_server_handshaker_factory_ex( + (const unsigned char **)config->pem_private_keys, + config->pem_private_keys_sizes, + (const unsigned char **)config->pem_cert_chains, + config->pem_cert_chains_sizes, config->num_key_cert_pairs, + config->pem_root_certs, config->pem_root_certs_size, + get_tsi_client_certificate_request_type( + config->client_certificate_request), + ssl_cipher_suites(), alpn_protocol_strings, alpn_protocol_string_lengths, + (uint16_t)num_alpn_protocols, &c->handshaker_factory); + if (result != TSI_OK) { + gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", + tsi_result_to_string(result)); + ssl_server_destroy(&c->base.base); + *sc = NULL; + goto error; + } + gpr_mu_init(&c->base.mu); + c->base.do_handshake = ssl_server_do_handshake; + *sc = &c->base; + gpr_free((void *)alpn_protocol_strings); + gpr_free(alpn_protocol_string_lengths); + return GRPC_SECURITY_OK; + +error: + gpr_free((void *)alpn_protocol_strings); + gpr_free(alpn_protocol_string_lengths); + return GRPC_SECURITY_ERROR; +} diff --git a/src/core/lib/security/transport/security_connector.h b/src/core/lib/security/transport/security_connector.h new file mode 100644 index 0000000000..84e586deaa --- /dev/null +++ b/src/core/lib/security/transport/security_connector.h @@ -0,0 +1,266 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H +#define GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H + +#include +#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/tcp_server.h" +#include "src/core/lib/tsi/transport_security_interface.h" + +/* --- status enum. --- */ + +typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status; + +/* --- URL schemes. --- */ + +#define GRPC_SSL_URL_SCHEME "https" +#define GRPC_FAKE_SECURITY_URL_SCHEME "http+fake_security" + +/* --- security_connector object. --- + + A security connector object represents away to configure the underlying + transport security mechanism and check the resulting trusted peer. */ + +typedef struct grpc_security_connector grpc_security_connector; + +#define GRPC_SECURITY_CONNECTOR_ARG "grpc.security_connector" + +typedef void (*grpc_security_peer_check_cb)(grpc_exec_ctx *exec_ctx, + void *user_data, + grpc_security_status status, + grpc_auth_context *auth_context); + +/* Ownership of the secure_endpoint is transfered. */ +typedef void (*grpc_security_handshake_done_cb)( + grpc_exec_ctx *exec_ctx, void *user_data, grpc_security_status status, + grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context); + +typedef struct { + void (*destroy)(grpc_security_connector *sc); + void (*check_peer)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc, + tsi_peer peer, grpc_security_peer_check_cb cb, + void *user_data); +} grpc_security_connector_vtable; + +typedef struct grpc_security_connector_handshake_list { + void *handshake; + struct grpc_security_connector_handshake_list *next; +} grpc_security_connector_handshake_list; + +struct grpc_security_connector { + const grpc_security_connector_vtable *vtable; + gpr_refcount refcount; + const char *url_scheme; +}; + +/* Refcounting. */ +#ifdef GRPC_SECURITY_CONNECTOR_REFCOUNT_DEBUG +#define GRPC_SECURITY_CONNECTOR_REF(p, r) \ + grpc_security_connector_ref((p), __FILE__, __LINE__, (r)) +#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) \ + grpc_security_connector_unref((p), __FILE__, __LINE__, (r)) +grpc_security_connector *grpc_security_connector_ref( + grpc_security_connector *policy, const char *file, int line, + const char *reason); +void grpc_security_connector_unref(grpc_security_connector *policy, + const char *file, int line, + const char *reason); +#else +#define GRPC_SECURITY_CONNECTOR_REF(p, r) grpc_security_connector_ref((p)) +#define GRPC_SECURITY_CONNECTOR_UNREF(p, r) grpc_security_connector_unref((p)) +grpc_security_connector *grpc_security_connector_ref( + grpc_security_connector *policy); +void grpc_security_connector_unref(grpc_security_connector *policy); +#endif + +/* Check the peer. Callee takes ownership of the peer object. + The callback will include the resulting auth_context. */ +void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx, + grpc_security_connector *sc, + tsi_peer peer, + grpc_security_peer_check_cb cb, + void *user_data); + +/* Util to encapsulate the connector in a channel arg. */ +grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc); + +/* Util to get the connector from a channel arg. */ +grpc_security_connector *grpc_security_connector_from_arg(const grpc_arg *arg); + +/* Util to find the connector from channel args. */ +grpc_security_connector *grpc_find_security_connector_in_args( + const grpc_channel_args *args); + +/* --- channel_security_connector object. --- + + A channel security connector object represents away to configure the + underlying transport security mechanism on the client side. */ + +typedef struct grpc_channel_security_connector grpc_channel_security_connector; + +typedef void (*grpc_security_call_host_check_cb)(grpc_exec_ctx *exec_ctx, + void *user_data, + grpc_security_status status); + +struct grpc_channel_security_connector { + grpc_security_connector base; + grpc_call_credentials *request_metadata_creds; + void (*check_call_host)(grpc_exec_ctx *exec_ctx, + grpc_channel_security_connector *sc, const char *host, + grpc_auth_context *auth_context, + grpc_security_call_host_check_cb cb, void *user_data); + void (*do_handshake)(grpc_exec_ctx *exec_ctx, + grpc_channel_security_connector *sc, + grpc_endpoint *nonsecure_endpoint, + grpc_security_handshake_done_cb cb, void *user_data); +}; + +/* Checks that the host that will be set for a call is acceptable. */ +void grpc_channel_security_connector_check_call_host( + grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc, + const char *host, grpc_auth_context *auth_context, + grpc_security_call_host_check_cb cb, void *user_data); + +/* Handshake. */ +void grpc_channel_security_connector_do_handshake( + grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector, + grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb, + void *user_data); + +/* --- server_security_connector object. --- + + A server security connector object represents away to configure the + underlying transport security mechanism on the server side. */ + +typedef struct grpc_server_security_connector grpc_server_security_connector; + +struct grpc_server_security_connector { + grpc_security_connector base; + gpr_mu mu; + grpc_security_connector_handshake_list *handshaking_handshakes; + const grpc_channel_args *channel_args; + void (*do_handshake)(grpc_exec_ctx *exec_ctx, + grpc_server_security_connector *sc, + grpc_tcp_server_acceptor *acceptor, + grpc_endpoint *nonsecure_endpoint, + grpc_security_handshake_done_cb cb, void *user_data); +}; + +void grpc_server_security_connector_do_handshake( + grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc, + grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint, + grpc_security_handshake_done_cb cb, void *user_data); + +void grpc_server_security_connector_shutdown( + grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector); + +/* --- Creation security connectors. --- */ + +/* For TESTING ONLY! + Creates a fake connector that emulates real channel security. */ +grpc_channel_security_connector *grpc_fake_channel_security_connector_create( + grpc_call_credentials *request_metadata_creds); + +/* For TESTING ONLY! + Creates a fake connector that emulates real server security. */ +grpc_server_security_connector *grpc_fake_server_security_connector_create( + void); + +/* Config for ssl clients. */ +typedef struct { + unsigned char *pem_private_key; + size_t pem_private_key_size; + unsigned char *pem_cert_chain; + size_t pem_cert_chain_size; + unsigned char *pem_root_certs; + size_t pem_root_certs_size; +} grpc_ssl_config; + +/* Creates an SSL channel_security_connector. + - request_metadata_creds is the credentials object which metadata + will be sent with each request. This parameter can be NULL. + - config is the SSL config to be used for the SSL channel establishment. + - is_client should be 0 for a server or a non-0 value for a client. + - secure_peer_name is the secure peer name that should be checked in + grpc_channel_security_connector_check_peer. This parameter may be NULL in + which case the peer name will not be checked. Note that if this parameter + is not NULL, then, pem_root_certs should not be NULL either. + - sc is a pointer on the connector to be created. + This function returns GRPC_SECURITY_OK in case of success or a + specific error code otherwise. +*/ +grpc_security_status grpc_ssl_channel_security_connector_create( + grpc_call_credentials *request_metadata_creds, + const grpc_ssl_config *config, const char *target_name, + const char *overridden_target_name, grpc_channel_security_connector **sc); + +/* Gets the default ssl roots. */ +size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs); + +/* Exposed for TESTING ONLY!. */ +gpr_slice grpc_get_default_ssl_roots_for_testing(void); + +/* Config for ssl servers. */ +typedef struct { + unsigned char **pem_private_keys; + size_t *pem_private_keys_sizes; + unsigned char **pem_cert_chains; + size_t *pem_cert_chains_sizes; + size_t num_key_cert_pairs; + unsigned char *pem_root_certs; + size_t pem_root_certs_size; + grpc_ssl_client_certificate_request_type client_certificate_request; +} grpc_ssl_server_config; + +/* Creates an SSL server_security_connector. + - config is the SSL config to be used for the SSL channel establishment. + - sc is a pointer on the connector to be created. + This function returns GRPC_SECURITY_OK in case of success or a + specific error code otherwise. +*/ +grpc_security_status grpc_ssl_server_security_connector_create( + const grpc_ssl_server_config *config, grpc_server_security_connector **sc); + +/* Util. */ +const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer, + const char *name); + +/* Exposed for testing only. */ +grpc_auth_context *tsi_ssl_peer_to_auth_context(const tsi_peer *peer); +tsi_peer tsi_shallow_peer_from_ssl_auth_context( + const grpc_auth_context *auth_context); +void tsi_shallow_peer_destruct(tsi_peer *peer); + +#endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_CONNECTOR_H */ diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c new file mode 100644 index 0000000000..006a30f0c6 --- /dev/null +++ b/src/core/lib/security/transport/server_auth_filter.c @@ -0,0 +1,264 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/transport/auth_filters.h" + +#include +#include + +typedef struct call_data { + grpc_metadata_batch *recv_initial_metadata; + /* Closure to call when finished with the auth_on_recv hook. */ + grpc_closure *on_done_recv; + /* Receive closures are chained: we inject this closure as the on_done_recv + up-call on transport_op, and remember to call our on_done_recv member after + handling it. */ + grpc_closure auth_on_recv; + grpc_transport_stream_op transport_op; + grpc_metadata_array md; + const grpc_metadata *consumed_md; + size_t num_consumed_md; + grpc_auth_context *auth_context; +} call_data; + +typedef struct channel_data { + grpc_auth_context *auth_context; + grpc_server_credentials *creds; +} channel_data; + +static grpc_metadata_array metadata_batch_to_md_array( + const grpc_metadata_batch *batch) { + grpc_linked_mdelem *l; + grpc_metadata_array result; + grpc_metadata_array_init(&result); + for (l = batch->list.head; l != NULL; l = l->next) { + grpc_metadata *usr_md = NULL; + grpc_mdelem *md = l->md; + grpc_mdstr *key = md->key; + grpc_mdstr *value = md->value; + if (result.count == result.capacity) { + result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2); + result.metadata = + gpr_realloc(result.metadata, result.capacity * sizeof(grpc_metadata)); + } + usr_md = &result.metadata[result.count++]; + usr_md->key = grpc_mdstr_as_c_string(key); + usr_md->value = grpc_mdstr_as_c_string(value); + usr_md->value_length = GPR_SLICE_LENGTH(value->slice); + } + return result; +} + +static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) { + grpc_call_element *elem = user_data; + call_data *calld = elem->call_data; + size_t i; + for (i = 0; i < calld->num_consumed_md; i++) { + const grpc_metadata *consumed_md = &calld->consumed_md[i]; + /* Maybe we could do a pointer comparison but we do not have any guarantee + that the metadata processor used the same pointers for consumed_md in the + callback. */ + if (GPR_SLICE_LENGTH(md->key->slice) != strlen(consumed_md->key) || + GPR_SLICE_LENGTH(md->value->slice) != consumed_md->value_length) { + continue; + } + if (memcmp(GPR_SLICE_START_PTR(md->key->slice), consumed_md->key, + GPR_SLICE_LENGTH(md->key->slice)) == 0 && + memcmp(GPR_SLICE_START_PTR(md->value->slice), consumed_md->value, + GPR_SLICE_LENGTH(md->value->slice)) == 0) { + return NULL; /* Delete. */ + } + } + return md; +} + +/* called from application code */ +static void on_md_processing_done( + void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md, + const grpc_metadata *response_md, size_t num_response_md, + grpc_status_code status, const char *error_details) { + grpc_call_element *elem = user_data; + call_data *calld = elem->call_data; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + /* TODO(jboeuf): Implement support for response_md. */ + if (response_md != NULL && num_response_md > 0) { + gpr_log(GPR_INFO, + "response_md in auth metadata processing not supported for now. " + "Ignoring..."); + } + + if (status == GRPC_STATUS_OK) { + calld->consumed_md = consumed_md; + calld->num_consumed_md = num_consumed_md; + grpc_metadata_batch_filter(calld->recv_initial_metadata, remove_consumed_md, + elem); + grpc_metadata_array_destroy(&calld->md); + calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 1); + } else { + gpr_slice message; + grpc_transport_stream_op close_op; + memset(&close_op, 0, sizeof(close_op)); + grpc_metadata_array_destroy(&calld->md); + error_details = error_details != NULL + ? error_details + : "Authentication metadata processing failed."; + message = gpr_slice_from_copied_string(error_details); + calld->transport_op.send_initial_metadata = NULL; + if (calld->transport_op.send_message != NULL) { + grpc_byte_stream_destroy(&exec_ctx, calld->transport_op.send_message); + calld->transport_op.send_message = NULL; + } + calld->transport_op.send_trailing_metadata = NULL; + grpc_transport_stream_op_add_close(&close_op, status, &message); + grpc_call_next_op(&exec_ctx, elem, &close_op); + calld->on_done_recv->cb(&exec_ctx, calld->on_done_recv->cb_arg, 0); + } + + grpc_exec_ctx_finish(&exec_ctx); +} + +static void auth_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, + bool success) { + grpc_call_element *elem = user_data; + call_data *calld = elem->call_data; + channel_data *chand = elem->channel_data; + if (success) { + if (chand->creds->processor.process != NULL) { + calld->md = metadata_batch_to_md_array(calld->recv_initial_metadata); + chand->creds->processor.process( + chand->creds->processor.state, calld->auth_context, + calld->md.metadata, calld->md.count, on_md_processing_done, elem); + return; + } + } + calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success); +} + +static void set_recv_ops_md_callbacks(grpc_call_element *elem, + grpc_transport_stream_op *op) { + call_data *calld = elem->call_data; + + if (op->recv_initial_metadata != NULL) { + /* substitute our callback for the higher callback */ + calld->recv_initial_metadata = op->recv_initial_metadata; + calld->on_done_recv = op->recv_initial_metadata_ready; + op->recv_initial_metadata_ready = &calld->auth_on_recv; + calld->transport_op = *op; + } +} + +/* Called either: + - in response to an API call (or similar) from above, to send something + - a network event (or similar) from below, to receive something + op contains type and call direction information, in addition to the data + that is being sent or received. */ +static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_transport_stream_op *op) { + set_recv_ops_md_callbacks(elem, op); + grpc_call_next_op(exec_ctx, elem, op); +} + +/* Constructor for call_data */ +static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_call_element_args *args) { + /* grab pointers to our data from the call element */ + call_data *calld = elem->call_data; + channel_data *chand = elem->channel_data; + grpc_server_security_context *server_ctx = NULL; + + /* initialize members */ + memset(calld, 0, sizeof(*calld)); + grpc_closure_init(&calld->auth_on_recv, auth_on_recv, elem); + + if (args->context[GRPC_CONTEXT_SECURITY].value != NULL) { + args->context[GRPC_CONTEXT_SECURITY].destroy( + args->context[GRPC_CONTEXT_SECURITY].value); + } + + server_ctx = grpc_server_security_context_create(); + server_ctx->auth_context = grpc_auth_context_create(chand->auth_context); + calld->auth_context = server_ctx->auth_context; + + args->context[GRPC_CONTEXT_SECURITY].value = server_ctx; + args->context[GRPC_CONTEXT_SECURITY].destroy = + grpc_server_security_context_destroy; +} + +static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_pollset *pollset) {} + +/* Destructor for call_data */ +static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + void *ignored) {} + +/* Constructor for channel_data */ +static void init_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem, + grpc_channel_element_args *args) { + grpc_auth_context *auth_context = + grpc_find_auth_context_in_args(args->channel_args); + grpc_server_credentials *creds = + grpc_find_server_credentials_in_args(args->channel_args); + /* grab pointers to our data from the channel element */ + channel_data *chand = elem->channel_data; + + GPR_ASSERT(!args->is_last); + GPR_ASSERT(auth_context != NULL); + GPR_ASSERT(creds != NULL); + + /* initialize members */ + chand->auth_context = + GRPC_AUTH_CONTEXT_REF(auth_context, "server_auth_filter"); + chand->creds = grpc_server_credentials_ref(creds); +} + +/* Destructor for channel data */ +static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem) { + /* grab pointers to our data from the channel element */ + channel_data *chand = elem->channel_data; + GRPC_AUTH_CONTEXT_UNREF(chand->auth_context, "server_auth_filter"); + grpc_server_credentials_unref(chand->creds); +} + +const grpc_channel_filter grpc_server_auth_filter = { + auth_start_transport_op, grpc_channel_next_op, sizeof(call_data), + init_call_elem, set_pollset, destroy_call_elem, + sizeof(channel_data), init_channel_elem, destroy_channel_elem, + grpc_call_next_get_peer, "server-auth"}; diff --git a/src/core/lib/security/util/b64.c b/src/core/lib/security/util/b64.c new file mode 100644 index 0000000000..9da42e4e73 --- /dev/null +++ b/src/core/lib/security/util/b64.c @@ -0,0 +1,233 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/util/b64.h" + +#include +#include + +#include +#include +#include + +/* --- Constants. --- */ + +static const int8_t base64_bytes[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 0x3E, -1, -1, -1, 0x3F, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, -1, -1, + -1, 0x7F, -1, -1, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, -1, -1, -1, -1, -1, + -1, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, + 0x31, 0x32, 0x33, -1, -1, -1, -1, -1}; + +static const char base64_url_unsafe_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char base64_url_safe_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + +#define GRPC_BASE64_PAD_CHAR '=' +#define GRPC_BASE64_PAD_BYTE 0x7F +#define GRPC_BASE64_MULTILINE_LINE_LEN 76 +#define GRPC_BASE64_MULTILINE_NUM_BLOCKS (GRPC_BASE64_MULTILINE_LINE_LEN / 4) + +/* --- base64 functions. --- */ + +char *grpc_base64_encode(const void *vdata, size_t data_size, int url_safe, + int multiline) { + const unsigned char *data = vdata; + const char *base64_chars = + url_safe ? base64_url_safe_chars : base64_url_unsafe_chars; + size_t result_projected_size = + 4 * ((data_size + 3) / 3) + + 2 * (multiline ? (data_size / (3 * GRPC_BASE64_MULTILINE_NUM_BLOCKS)) + : 0) + + 1; + char *result = gpr_malloc(result_projected_size); + char *current = result; + size_t num_blocks = 0; + size_t i = 0; + + /* Encode each block. */ + while (data_size >= 3) { + *current++ = base64_chars[(data[i] >> 2) & 0x3F]; + *current++ = + base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)]; + *current++ = + base64_chars[((data[i + 1] & 0x0F) << 2) | ((data[i + 2] >> 6) & 0x03)]; + *current++ = base64_chars[data[i + 2] & 0x3F]; + + data_size -= 3; + i += 3; + if (multiline && (++num_blocks == GRPC_BASE64_MULTILINE_NUM_BLOCKS)) { + *current++ = '\r'; + *current++ = '\n'; + num_blocks = 0; + } + } + + /* Take care of the tail. */ + if (data_size == 2) { + *current++ = base64_chars[(data[i] >> 2) & 0x3F]; + *current++ = + base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)]; + *current++ = base64_chars[(data[i + 1] & 0x0F) << 2]; + *current++ = GRPC_BASE64_PAD_CHAR; + } else if (data_size == 1) { + *current++ = base64_chars[(data[i] >> 2) & 0x3F]; + *current++ = base64_chars[(data[i] & 0x03) << 4]; + *current++ = GRPC_BASE64_PAD_CHAR; + *current++ = GRPC_BASE64_PAD_CHAR; + } + + GPR_ASSERT(current >= result); + GPR_ASSERT((uintptr_t)(current - result) < result_projected_size); + result[current - result] = '\0'; + return result; +} + +gpr_slice grpc_base64_decode(const char *b64, int url_safe) { + return grpc_base64_decode_with_len(b64, strlen(b64), url_safe); +} + +static void decode_one_char(const unsigned char *codes, unsigned char *result, + size_t *result_offset) { + uint32_t packed = ((uint32_t)codes[0] << 2) | ((uint32_t)codes[1] >> 4); + result[(*result_offset)++] = (unsigned char)packed; +} + +static void decode_two_chars(const unsigned char *codes, unsigned char *result, + size_t *result_offset) { + uint32_t packed = ((uint32_t)codes[0] << 10) | ((uint32_t)codes[1] << 4) | + ((uint32_t)codes[2] >> 2); + result[(*result_offset)++] = (unsigned char)(packed >> 8); + result[(*result_offset)++] = (unsigned char)(packed); +} + +static int decode_group(const unsigned char *codes, size_t num_codes, + unsigned char *result, size_t *result_offset) { + GPR_ASSERT(num_codes <= 4); + + /* Short end groups that may not have padding. */ + if (num_codes == 1) { + gpr_log(GPR_ERROR, "Invalid group. Must be at least 2 bytes."); + return 0; + } + if (num_codes == 2) { + decode_one_char(codes, result, result_offset); + return 1; + } + if (num_codes == 3) { + decode_two_chars(codes, result, result_offset); + return 1; + } + + /* Regular 4 byte groups with padding or not. */ + GPR_ASSERT(num_codes == 4); + if (codes[0] == GRPC_BASE64_PAD_BYTE || codes[1] == GRPC_BASE64_PAD_BYTE) { + gpr_log(GPR_ERROR, "Invalid padding detected."); + return 0; + } + if (codes[2] == GRPC_BASE64_PAD_BYTE) { + if (codes[3] == GRPC_BASE64_PAD_BYTE) { + decode_one_char(codes, result, result_offset); + } else { + gpr_log(GPR_ERROR, "Invalid padding detected."); + return 0; + } + } else if (codes[3] == GRPC_BASE64_PAD_BYTE) { + decode_two_chars(codes, result, result_offset); + } else { + /* No padding. */ + uint32_t packed = ((uint32_t)codes[0] << 18) | ((uint32_t)codes[1] << 12) | + ((uint32_t)codes[2] << 6) | codes[3]; + result[(*result_offset)++] = (unsigned char)(packed >> 16); + result[(*result_offset)++] = (unsigned char)(packed >> 8); + result[(*result_offset)++] = (unsigned char)(packed); + } + return 1; +} + +gpr_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len, + int url_safe) { + gpr_slice result = gpr_slice_malloc(b64_len); + unsigned char *current = GPR_SLICE_START_PTR(result); + size_t result_size = 0; + unsigned char codes[4]; + size_t num_codes = 0; + + while (b64_len--) { + unsigned char c = (unsigned char)(*b64++); + signed char code; + if (c >= GPR_ARRAY_SIZE(base64_bytes)) continue; + if (url_safe) { + if (c == '+' || c == '/') { + gpr_log(GPR_ERROR, "Invalid character for url safe base64 %c", c); + goto fail; + } + if (c == '-') { + c = '+'; + } else if (c == '_') { + c = '/'; + } + } + code = base64_bytes[c]; + if (code == -1) { + if (c != '\r' && c != '\n') { + gpr_log(GPR_ERROR, "Invalid character %c", c); + goto fail; + } + } else { + codes[num_codes++] = (unsigned char)code; + if (num_codes == 4) { + if (!decode_group(codes, num_codes, current, &result_size)) goto fail; + num_codes = 0; + } + } + } + + if (num_codes != 0 && + !decode_group(codes, num_codes, current, &result_size)) { + goto fail; + } + GPR_SLICE_SET_LENGTH(result, result_size); + return result; + +fail: + gpr_slice_unref(result); + return gpr_empty_slice(); +} diff --git a/src/core/lib/security/util/b64.h b/src/core/lib/security/util/b64.h new file mode 100644 index 0000000000..6908095287 --- /dev/null +++ b/src/core/lib/security/util/b64.h @@ -0,0 +1,52 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_UTIL_B64_H +#define GRPC_CORE_LIB_SECURITY_UTIL_B64_H + +#include + +/* Encodes data using base64. It is the caller's responsability to free + the returned char * using gpr_free. Returns NULL on NULL input. */ +char *grpc_base64_encode(const void *data, size_t data_size, int url_safe, + int multiline); + +/* Decodes data according to the base64 specification. Returns an empty + slice in case of failure. */ +gpr_slice grpc_base64_decode(const char *b64, int url_safe); + +/* Same as above except that the length is provided by the caller. */ +gpr_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len, + int url_safe); + +#endif /* GRPC_CORE_LIB_SECURITY_UTIL_B64_H */ diff --git a/src/core/lib/security/util/json_util.c b/src/core/lib/security/util/json_util.c new file mode 100644 index 0000000000..9eda12c628 --- /dev/null +++ b/src/core/lib/security/util/json_util.c @@ -0,0 +1,62 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/security/util/json_util.h" + +#include + +#include +#include + +const char *grpc_json_get_string_property(const grpc_json *json, + const char *prop_name) { + grpc_json *child; + for (child = json->child; child != NULL; child = child->next) { + if (strcmp(child->key, prop_name) == 0) break; + } + if (child == NULL || child->type != GRPC_JSON_STRING) { + gpr_log(GPR_ERROR, "Invalid or missing %s property.", prop_name); + return NULL; + } + return child->value; +} + +bool grpc_copy_json_string_property(const grpc_json *json, + const char *prop_name, + char **copied_value) { + const char *prop_value = grpc_json_get_string_property(json, prop_name); + if (prop_value == NULL) return false; + *copied_value = gpr_strdup(prop_value); + return true; +} + diff --git a/src/core/lib/security/util/json_util.h b/src/core/lib/security/util/json_util.h new file mode 100644 index 0000000000..3046412729 --- /dev/null +++ b/src/core/lib/security/util/json_util.h @@ -0,0 +1,57 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_UTIL_JSON_UTIL_H +#define GRPC_CORE_LIB_SECURITY_UTIL_JSON_UTIL_H + +#include + +#include "src/core/lib/json/json.h" + +// Constants. +#define GRPC_AUTH_JSON_TYPE_INVALID "invalid" +#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account" +#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user" + +// Gets a child property from a json node. +const char *grpc_json_get_string_property(const grpc_json *json, + const char *prop_name); + +// Copies the value of the json child property specified by prop_name. +// Returns false if the property was not found. +bool grpc_copy_json_string_property(const grpc_json *json, + const char *prop_name, + char **copied_value); + +#endif // GRPC_CORE_LIB_SECURITY_UTIL_JSON_UTIL_H + diff --git a/src/core/lib/surface/init_secure.c b/src/core/lib/surface/init_secure.c index 3fda2c9e1e..7ee7b51568 100644 --- a/src/core/lib/surface/init_secure.c +++ b/src/core/lib/surface/init_secure.c @@ -37,10 +37,10 @@ #include #include "src/core/lib/debug/trace.h" -#include "src/core/lib/security/auth_filters.h" -#include "src/core/lib/security/credentials.h" -#include "src/core/lib/security/secure_endpoint.h" -#include "src/core/lib/security/security_connector.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/transport/auth_filters.h" +#include "src/core/lib/security/transport/secure_endpoint.h" +#include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/tsi/transport_security_interface.h" diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index dab62530aa..0f0678a2cd 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -182,20 +182,28 @@ CORE_SOURCE_FILES = [ 'src/core/ext/transport/chttp2/transport/writing.c', 'src/core/ext/transport/chttp2/alpn/alpn.c', 'src/core/lib/http/httpcli_security_connector.c', - 'src/core/lib/security/b64.c', - 'src/core/lib/security/client_auth_filter.c', - 'src/core/lib/security/credentials.c', - 'src/core/lib/security/credentials_metadata.c', - 'src/core/lib/security/credentials_posix.c', - 'src/core/lib/security/credentials_win32.c', - 'src/core/lib/security/google_default_credentials.c', - 'src/core/lib/security/handshake.c', - 'src/core/lib/security/json_token.c', - 'src/core/lib/security/jwt_verifier.c', - 'src/core/lib/security/secure_endpoint.c', - 'src/core/lib/security/security_connector.c', - 'src/core/lib/security/security_context.c', - 'src/core/lib/security/server_auth_filter.c', + 'src/core/lib/security/context/security_context.c', + 'src/core/lib/security/credentials/composite/composite_credentials.c', + 'src/core/lib/security/credentials/credentials.c', + 'src/core/lib/security/credentials/credentials_metadata.c', + 'src/core/lib/security/credentials/fake/fake_credentials.c', + 'src/core/lib/security/credentials/google_default/credentials_posix.c', + 'src/core/lib/security/credentials/google_default/credentials_win32.c', + 'src/core/lib/security/credentials/google_default/google_default_credentials.c', + 'src/core/lib/security/credentials/iam/iam_credentials.c', + 'src/core/lib/security/credentials/jwt/json_token.c', + 'src/core/lib/security/credentials/jwt/jwt_credentials.c', + 'src/core/lib/security/credentials/jwt/jwt_verifier.c', + 'src/core/lib/security/credentials/oauth2/oauth2_credentials.c', + 'src/core/lib/security/credentials/plugin/plugin_credentials.c', + 'src/core/lib/security/credentials/ssl/ssl_credentials.c', + 'src/core/lib/security/transport/client_auth_filter.c', + 'src/core/lib/security/transport/handshake.c', + 'src/core/lib/security/transport/secure_endpoint.c', + 'src/core/lib/security/transport/security_connector.c', + 'src/core/lib/security/transport/server_auth_filter.c', + 'src/core/lib/security/util/b64.c', + 'src/core/lib/security/util/json_util.c', 'src/core/lib/surface/init_secure.c', 'src/core/lib/tsi/fake_transport_security.c', 'src/core/lib/tsi/ssl_transport_security.c', diff --git a/test/core/client_config/set_initial_connect_string_test.c b/test/core/client_config/set_initial_connect_string_test.c index 83058d9b2c..3ad8ce964a 100644 --- a/test/core/client_config/set_initial_connect_string_test.c +++ b/test/core/client_config/set_initial_connect_string_test.c @@ -40,7 +40,7 @@ #include "src/core/ext/client_config/initial_connect_string.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/support/string.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" diff --git a/test/core/end2end/fixtures/h2_fakesec.c b/test/core/end2end/fixtures/h2_fakesec.c index 246619bf68..44408b28af 100644 --- a/test/core/end2end/fixtures/h2_fakesec.c +++ b/test/core/end2end/fixtures/h2_fakesec.c @@ -40,7 +40,7 @@ #include #include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "test/core/end2end/data/ssl_test_data.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" diff --git a/test/core/end2end/fixtures/h2_oauth2.c b/test/core/end2end/fixtures/h2_oauth2.c index 550ff33140..fc56998cdb 100644 --- a/test/core/end2end/fixtures/h2_oauth2.c +++ b/test/core/end2end/fixtures/h2_oauth2.c @@ -41,7 +41,7 @@ #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" #include "test/core/end2end/data/ssl_test_data.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" diff --git a/test/core/end2end/fixtures/h2_ssl.c b/test/core/end2end/fixtures/h2_ssl.c index 69f7616074..eb28623264 100644 --- a/test/core/end2end/fixtures/h2_ssl.c +++ b/test/core/end2end/fixtures/h2_ssl.c @@ -41,7 +41,7 @@ #include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/support/tmpfile.h" diff --git a/test/core/end2end/fixtures/h2_ssl_cert.c b/test/core/end2end/fixtures/h2_ssl_cert.c index cd031ca482..2a6d0d17af 100644 --- a/test/core/end2end/fixtures/h2_ssl_cert.c +++ b/test/core/end2end/fixtures/h2_ssl_cert.c @@ -41,7 +41,7 @@ #include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/support/tmpfile.h" diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.c b/test/core/end2end/fixtures/h2_ssl_proxy.c index 1403b760f5..8f8c081465 100644 --- a/test/core/end2end/fixtures/h2_ssl_proxy.c +++ b/test/core/end2end/fixtures/h2_ssl_proxy.c @@ -41,7 +41,7 @@ #include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/support/tmpfile.h" diff --git a/test/core/end2end/tests/call_creds.c b/test/core/end2end/tests/call_creds.c index b555bea740..5c6791f6f7 100644 --- a/test/core/end2end/tests/call_creds.c +++ b/test/core/end2end/tests/call_creds.c @@ -42,7 +42,7 @@ #include #include #include -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/support/string.h" #include "test/core/end2end/cq_verifier.h" diff --git a/test/core/security/auth_context_test.c b/test/core/security/auth_context_test.c index d1ead16235..e2f44ebe24 100644 --- a/test/core/security/auth_context_test.c +++ b/test/core/security/auth_context_test.c @@ -33,7 +33,7 @@ #include -#include "src/core/lib/security/security_context.h" +#include "src/core/lib/security/context/security_context.h" #include "src/core/lib/support/string.h" #include "test/core/util/test_config.h" diff --git a/test/core/security/b64_test.c b/test/core/security/b64_test.c index cea870321d..b26bd026fd 100644 --- a/test/core/security/b64_test.c +++ b/test/core/security/b64_test.c @@ -31,7 +31,7 @@ * */ -#include "src/core/lib/security/b64.h" +#include "src/core/lib/security/util/b64.h" #include diff --git a/test/core/security/create_jwt.c b/test/core/security/create_jwt.c index 6d4707f3c7..3c36b767d3 100644 --- a/test/core/security/create_jwt.c +++ b/test/core/security/create_jwt.c @@ -34,8 +34,7 @@ #include #include -#include "src/core/lib/security/credentials.h" -#include "src/core/lib/security/json_token.h" +#include "src/core/lib/security/credentials/jwt/jwt_credentials.h" #include "src/core/lib/support/load_file.h" #include diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index 7867293278..31e06372b9 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -33,7 +33,7 @@ #include -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" #include #include @@ -45,7 +45,10 @@ #include #include "src/core/lib/http/httpcli.h" -#include "src/core/lib/security/json_token.h" +#include "src/core/lib/security/credentials/composite/composite_credentials.h" +#include "src/core/lib/security/credentials/google_default/google_default_credentials.h" +#include "src/core/lib/security/credentials/jwt/jwt_credentials.h" +#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/support/tmpfile.h" diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c index bd314e90d8..2a102fb139 100644 --- a/test/core/security/fetch_oauth2.c +++ b/test/core/security/fetch_oauth2.c @@ -42,7 +42,7 @@ #include #include -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/support/load_file.h" #include "test/core/security/oauth2_utils.h" diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c index 3aee52ee5c..405fe56c46 100644 --- a/test/core/security/json_token_test.c +++ b/test/core/security/json_token_test.c @@ -31,7 +31,7 @@ * */ -#include "src/core/lib/security/json_token.h" +#include "src/core/lib/security/credentials/jwt/json_token.h" #include #include @@ -42,7 +42,8 @@ #include #include "src/core/lib/json/json.h" -#include "src/core/lib/security/b64.h" +#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" +#include "src/core/lib/security/util/b64.h" #include "test/core/util/test_config.h" /* This JSON key was generated with the GCE console and revoked immediately. diff --git a/test/core/security/jwt_verifier_test.c b/test/core/security/jwt_verifier_test.c index 077f44d1d6..50bf25171c 100644 --- a/test/core/security/jwt_verifier_test.c +++ b/test/core/security/jwt_verifier_test.c @@ -31,7 +31,7 @@ * */ -#include "src/core/lib/security/jwt_verifier.h" +#include "src/core/lib/security/credentials/jwt/jwt_verifier.h" #include @@ -43,8 +43,8 @@ #include #include "src/core/lib/http/httpcli.h" -#include "src/core/lib/security/b64.h" -#include "src/core/lib/security/json_token.h" +#include "src/core/lib/security/util/b64.h" +#include "src/core/lib/security/credentials/jwt/json_token.h" #include "test/core/util/test_config.h" /* This JSON key was generated with the GCE console and revoked immediately. diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c index 20815d184c..80d21cc602 100644 --- a/test/core/security/oauth2_utils.c +++ b/test/core/security/oauth2_utils.c @@ -42,7 +42,7 @@ #include #include -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" typedef struct { gpr_mu *mu; diff --git a/test/core/security/oauth2_utils.h b/test/core/security/oauth2_utils.h index eff98270c8..0f4e8857b0 100644 --- a/test/core/security/oauth2_utils.h +++ b/test/core/security/oauth2_utils.h @@ -34,7 +34,7 @@ #ifndef GRPC_TEST_CORE_SECURITY_OAUTH2_UTILS_H #define GRPC_TEST_CORE_SECURITY_OAUTH2_UTILS_H -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" #ifdef __cplusplus extern "C" { diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c index 99bce4fbdf..10a5e5224e 100644 --- a/test/core/security/print_google_default_creds_token.c +++ b/test/core/security/print_google_default_creds_token.c @@ -42,7 +42,8 @@ #include #include -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/credentials/composite/composite_credentials.h" #include "src/core/lib/support/string.h" typedef struct { diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c index aeaf38209b..6aba21a98c 100644 --- a/test/core/security/secure_endpoint_test.c +++ b/test/core/security/secure_endpoint_test.c @@ -41,7 +41,7 @@ #include #include "src/core/lib/iomgr/endpoint_pair.h" #include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/security/secure_endpoint.h" +#include "src/core/lib/security/transport/secure_endpoint.h" #include "src/core/lib/tsi/fake_transport_security.h" #include "test/core/util/test_config.h" diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c index 1a4e64b30c..6106bec9d3 100644 --- a/test/core/security/security_connector_test.c +++ b/test/core/security/security_connector_test.c @@ -40,8 +40,8 @@ #include #include -#include "src/core/lib/security/security_connector.h" -#include "src/core/lib/security/security_context.h" +#include "src/core/lib/security/context/security_context.h" +#include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" #include "src/core/lib/support/tmpfile.h" diff --git a/test/core/security/verify_jwt.c b/test/core/security/verify_jwt.c index 2274fe18d8..ecb873b655 100644 --- a/test/core/security/verify_jwt.c +++ b/test/core/security/verify_jwt.c @@ -42,7 +42,7 @@ #include #include -#include "src/core/lib/security/jwt_verifier.h" +#include "src/core/lib/security/credentials/jwt/jwt_verifier.h" typedef struct { grpc_pollset *pollset; diff --git a/test/core/surface/secure_channel_create_test.c b/test/core/surface/secure_channel_create_test.c index 80419efce4..b952503167 100644 --- a/test/core/surface/secure_channel_create_test.c +++ b/test/core/surface/secure_channel_create_test.c @@ -37,8 +37,8 @@ #include #include #include "src/core/ext/client_config/resolver_registry.h" -#include "src/core/lib/security/credentials.h" -#include "src/core/lib/security/security_connector.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "src/core/lib/security/transport/security_connector.h" #include "src/core/lib/surface/channel.h" #include "test/core/util/test_config.h" diff --git a/test/core/surface/server_chttp2_test.c b/test/core/surface/server_chttp2_test.c index d22c164972..f42ca9f9cd 100644 --- a/test/core/surface/server_chttp2_test.c +++ b/test/core/surface/server_chttp2_test.c @@ -37,7 +37,8 @@ #include #include #include -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/tsi/fake_transport_security.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" diff --git a/test/cpp/common/auth_property_iterator_test.cc b/test/cpp/common/auth_property_iterator_test.cc index 0e43d4e1e0..66225ff335 100644 --- a/test/cpp/common/auth_property_iterator_test.cc +++ b/test/cpp/common/auth_property_iterator_test.cc @@ -38,7 +38,7 @@ #include "test/cpp/util/string_ref_helper.h" extern "C" { -#include "src/core/lib/security/security_context.h" +#include "src/core/lib/security/context/security_context.h" } using ::grpc::testing::ToString; diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc index 067361334d..b131452f73 100644 --- a/test/cpp/common/secure_auth_context_test.cc +++ b/test/cpp/common/secure_auth_context_test.cc @@ -38,7 +38,7 @@ #include "test/cpp/util/string_ref_helper.h" extern "C" { -#include "src/core/lib/security/security_context.h" +#include "src/core/lib/security/context/security_context.h" } using grpc::testing::ToString; diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 0c9313f88f..0311864759 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -48,7 +48,7 @@ #include #include -#include "src/core/lib/security/credentials.h" +#include "src/core/lib/security/credentials/credentials.h" #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/core/util/port.h" diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1b1453f7ea..260e68804e 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -882,15 +882,24 @@ src/core/ext/transport/chttp2/transport/stream_map.h \ src/core/ext/transport/chttp2/transport/timeout_encoding.h \ src/core/ext/transport/chttp2/transport/varint.h \ src/core/ext/transport/chttp2/alpn/alpn.h \ -src/core/lib/security/auth_filters.h \ -src/core/lib/security/b64.h \ -src/core/lib/security/credentials.h \ -src/core/lib/security/handshake.h \ -src/core/lib/security/json_token.h \ -src/core/lib/security/jwt_verifier.h \ -src/core/lib/security/secure_endpoint.h \ -src/core/lib/security/security_connector.h \ -src/core/lib/security/security_context.h \ +src/core/lib/security/context/security_context.h \ +src/core/lib/security/credentials/composite/composite_credentials.h \ +src/core/lib/security/credentials/credentials.h \ +src/core/lib/security/credentials/fake/fake_credentials.h \ +src/core/lib/security/credentials/google_default/google_default_credentials.h \ +src/core/lib/security/credentials/iam/iam_credentials.h \ +src/core/lib/security/credentials/jwt/json_token.h \ +src/core/lib/security/credentials/jwt/jwt_credentials.h \ +src/core/lib/security/credentials/jwt/jwt_verifier.h \ +src/core/lib/security/credentials/oauth2/oauth2_credentials.h \ +src/core/lib/security/credentials/plugin/plugin_credentials.h \ +src/core/lib/security/credentials/ssl/ssl_credentials.h \ +src/core/lib/security/transport/auth_filters.h \ +src/core/lib/security/transport/handshake.h \ +src/core/lib/security/transport/secure_endpoint.h \ +src/core/lib/security/transport/security_connector.h \ +src/core/lib/security/util/b64.h \ +src/core/lib/security/util/json_util.h \ src/core/lib/tsi/fake_transport_security.h \ src/core/lib/tsi/ssl_transport_security.h \ src/core/lib/tsi/ssl_types.h \ @@ -1030,20 +1039,28 @@ src/core/ext/transport/chttp2/transport/varint.c \ src/core/ext/transport/chttp2/transport/writing.c \ src/core/ext/transport/chttp2/alpn/alpn.c \ src/core/lib/http/httpcli_security_connector.c \ -src/core/lib/security/b64.c \ -src/core/lib/security/client_auth_filter.c \ -src/core/lib/security/credentials.c \ -src/core/lib/security/credentials_metadata.c \ -src/core/lib/security/credentials_posix.c \ -src/core/lib/security/credentials_win32.c \ -src/core/lib/security/google_default_credentials.c \ -src/core/lib/security/handshake.c \ -src/core/lib/security/json_token.c \ -src/core/lib/security/jwt_verifier.c \ -src/core/lib/security/secure_endpoint.c \ -src/core/lib/security/security_connector.c \ -src/core/lib/security/security_context.c \ -src/core/lib/security/server_auth_filter.c \ +src/core/lib/security/context/security_context.c \ +src/core/lib/security/credentials/composite/composite_credentials.c \ +src/core/lib/security/credentials/credentials.c \ +src/core/lib/security/credentials/credentials_metadata.c \ +src/core/lib/security/credentials/fake/fake_credentials.c \ +src/core/lib/security/credentials/google_default/credentials_posix.c \ +src/core/lib/security/credentials/google_default/credentials_win32.c \ +src/core/lib/security/credentials/google_default/google_default_credentials.c \ +src/core/lib/security/credentials/iam/iam_credentials.c \ +src/core/lib/security/credentials/jwt/json_token.c \ +src/core/lib/security/credentials/jwt/jwt_credentials.c \ +src/core/lib/security/credentials/jwt/jwt_verifier.c \ +src/core/lib/security/credentials/oauth2/oauth2_credentials.c \ +src/core/lib/security/credentials/plugin/plugin_credentials.c \ +src/core/lib/security/credentials/ssl/ssl_credentials.c \ +src/core/lib/security/transport/client_auth_filter.c \ +src/core/lib/security/transport/handshake.c \ +src/core/lib/security/transport/secure_endpoint.c \ +src/core/lib/security/transport/security_connector.c \ +src/core/lib/security/transport/server_auth_filter.c \ +src/core/lib/security/util/b64.c \ +src/core/lib/security/util/json_util.c \ src/core/lib/surface/init_secure.c \ src/core/lib/tsi/fake_transport_security.c \ src/core/lib/tsi/ssl_transport_security.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index f546f3b995..6c08a80882 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -6014,15 +6014,24 @@ "headers": [ "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", - "src/core/lib/security/auth_filters.h", - "src/core/lib/security/b64.h", - "src/core/lib/security/credentials.h", - "src/core/lib/security/handshake.h", - "src/core/lib/security/json_token.h", - "src/core/lib/security/jwt_verifier.h", - "src/core/lib/security/secure_endpoint.h", - "src/core/lib/security/security_connector.h", - "src/core/lib/security/security_context.h" + "src/core/lib/security/context/security_context.h", + "src/core/lib/security/credentials/composite/composite_credentials.h", + "src/core/lib/security/credentials/credentials.h", + "src/core/lib/security/credentials/fake/fake_credentials.h", + "src/core/lib/security/credentials/google_default/google_default_credentials.h", + "src/core/lib/security/credentials/iam/iam_credentials.h", + "src/core/lib/security/credentials/jwt/json_token.h", + "src/core/lib/security/credentials/jwt/jwt_credentials.h", + "src/core/lib/security/credentials/jwt/jwt_verifier.h", + "src/core/lib/security/credentials/oauth2/oauth2_credentials.h", + "src/core/lib/security/credentials/plugin/plugin_credentials.h", + "src/core/lib/security/credentials/ssl/ssl_credentials.h", + "src/core/lib/security/transport/auth_filters.h", + "src/core/lib/security/transport/handshake.h", + "src/core/lib/security/transport/secure_endpoint.h", + "src/core/lib/security/transport/security_connector.h", + "src/core/lib/security/util/b64.h", + "src/core/lib/security/util/json_util.h" ], "language": "c", "name": "grpc_secure", @@ -6030,29 +6039,46 @@ "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "src/core/lib/http/httpcli_security_connector.c", - "src/core/lib/security/auth_filters.h", - "src/core/lib/security/b64.c", - "src/core/lib/security/b64.h", - "src/core/lib/security/client_auth_filter.c", - "src/core/lib/security/credentials.c", - "src/core/lib/security/credentials.h", - "src/core/lib/security/credentials_metadata.c", - "src/core/lib/security/credentials_posix.c", - "src/core/lib/security/credentials_win32.c", - "src/core/lib/security/google_default_credentials.c", - "src/core/lib/security/handshake.c", - "src/core/lib/security/handshake.h", - "src/core/lib/security/json_token.c", - "src/core/lib/security/json_token.h", - "src/core/lib/security/jwt_verifier.c", - "src/core/lib/security/jwt_verifier.h", - "src/core/lib/security/secure_endpoint.c", - "src/core/lib/security/secure_endpoint.h", - "src/core/lib/security/security_connector.c", - "src/core/lib/security/security_connector.h", - "src/core/lib/security/security_context.c", - "src/core/lib/security/security_context.h", - "src/core/lib/security/server_auth_filter.c", + "src/core/lib/security/context/security_context.c", + "src/core/lib/security/context/security_context.h", + "src/core/lib/security/credentials/composite/composite_credentials.c", + "src/core/lib/security/credentials/composite/composite_credentials.h", + "src/core/lib/security/credentials/credentials.c", + "src/core/lib/security/credentials/credentials.h", + "src/core/lib/security/credentials/credentials_metadata.c", + "src/core/lib/security/credentials/fake/fake_credentials.c", + "src/core/lib/security/credentials/fake/fake_credentials.h", + "src/core/lib/security/credentials/google_default/credentials_posix.c", + "src/core/lib/security/credentials/google_default/credentials_win32.c", + "src/core/lib/security/credentials/google_default/google_default_credentials.c", + "src/core/lib/security/credentials/google_default/google_default_credentials.h", + "src/core/lib/security/credentials/iam/iam_credentials.c", + "src/core/lib/security/credentials/iam/iam_credentials.h", + "src/core/lib/security/credentials/jwt/json_token.c", + "src/core/lib/security/credentials/jwt/json_token.h", + "src/core/lib/security/credentials/jwt/jwt_credentials.c", + "src/core/lib/security/credentials/jwt/jwt_credentials.h", + "src/core/lib/security/credentials/jwt/jwt_verifier.c", + "src/core/lib/security/credentials/jwt/jwt_verifier.h", + "src/core/lib/security/credentials/oauth2/oauth2_credentials.c", + "src/core/lib/security/credentials/oauth2/oauth2_credentials.h", + "src/core/lib/security/credentials/plugin/plugin_credentials.c", + "src/core/lib/security/credentials/plugin/plugin_credentials.h", + "src/core/lib/security/credentials/ssl/ssl_credentials.c", + "src/core/lib/security/credentials/ssl/ssl_credentials.h", + "src/core/lib/security/transport/auth_filters.h", + "src/core/lib/security/transport/client_auth_filter.c", + "src/core/lib/security/transport/handshake.c", + "src/core/lib/security/transport/handshake.h", + "src/core/lib/security/transport/secure_endpoint.c", + "src/core/lib/security/transport/secure_endpoint.h", + "src/core/lib/security/transport/security_connector.c", + "src/core/lib/security/transport/security_connector.h", + "src/core/lib/security/transport/server_auth_filter.c", + "src/core/lib/security/util/b64.c", + "src/core/lib/security/util/b64.h", + "src/core/lib/security/util/json_util.c", + "src/core/lib/security/util/json_util.h", "src/core/lib/surface/init_secure.c" ], "third_party": false, diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 4eec05a3b1..8b8212ebf0 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -391,15 +391,24 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -647,33 +656,49 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 17c88c4805..f5f91a9b40 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -319,47 +319,71 @@ src\core\lib\http - - src\core\lib\security + + src\core\lib\security\context - - src\core\lib\security + + src\core\lib\security\credentials\composite - - src\core\lib\security + + src\core\lib\security\credentials - - src\core\lib\security + + src\core\lib\security\credentials - - src\core\lib\security + + src\core\lib\security\credentials\fake - - src\core\lib\security + + src\core\lib\security\credentials\google_default - - src\core\lib\security + + src\core\lib\security\credentials\google_default - - src\core\lib\security + + src\core\lib\security\credentials\google_default - - src\core\lib\security + + src\core\lib\security\credentials\iam - - src\core\lib\security + + src\core\lib\security\credentials\jwt - - src\core\lib\security + + src\core\lib\security\credentials\jwt - - src\core\lib\security + + src\core\lib\security\credentials\jwt - - src\core\lib\security + + src\core\lib\security\credentials\oauth2 - - src\core\lib\security + + src\core\lib\security\credentials\plugin + + + src\core\lib\security\credentials\ssl + + + src\core\lib\security\transport + + + src\core\lib\security\transport + + + src\core\lib\security\transport + + + src\core\lib\security\transport + + + src\core\lib\security\transport + + + src\core\lib\security\util + + + src\core\lib\security\util src\core\lib\surface @@ -866,32 +890,59 @@ src\core\ext\transport\chttp2\alpn - - src\core\lib\security + + src\core\lib\security\context + + + src\core\lib\security\credentials\composite + + + src\core\lib\security\credentials + + + src\core\lib\security\credentials\fake + + + src\core\lib\security\credentials\google_default + + + src\core\lib\security\credentials\iam + + + src\core\lib\security\credentials\jwt + + + src\core\lib\security\credentials\jwt - - src\core\lib\security + + src\core\lib\security\credentials\jwt - - src\core\lib\security + + src\core\lib\security\credentials\oauth2 - - src\core\lib\security + + src\core\lib\security\credentials\plugin - - src\core\lib\security + + src\core\lib\security\credentials\ssl - - src\core\lib\security + + src\core\lib\security\transport - - src\core\lib\security + + src\core\lib\security\transport - - src\core\lib\security + + src\core\lib\security\transport - - src\core\lib\security + + src\core\lib\security\transport + + + src\core\lib\security\util + + + src\core\lib\security\util src\core\lib\tsi @@ -1112,6 +1163,42 @@ {c4661d64-349f-01c1-1ba8-0602f9047595} + + {187b52e3-bc78-6c62-3e68-4eb19a257661} + + + {c8af33b1-f786-001d-3e92-140872dc9829} + + + {197ed135-5f84-9f6a-6751-38dc5e9dd38c} + + + {6d391299-53d7-ee6a-55aa-d4c46cd86e82} + + + {412c7418-e90a-de77-5705-7890ba960911} + + + {718f826c-994b-7dd4-3042-0e999c5c22ba} + + + {ab21bcdf-de99-5838-699a-19ecb0c4aa14} + + + {f47a7a32-3166-b899-3622-f062f372feea} + + + {46120bcc-03e3-1aaa-fc61-9cef786bd70c} + + + {9d7802bc-d459-1a9b-3c97-868cddcca1d1} + + + {b22e611f-8272-9914-24a5-8107ebf51eeb} + + + {fcd7b397-aadd-556a-8aae-0cb7c893fbe0} + {a21971fb-304f-da08-b1b2-7bd8df8ac373} -- cgit v1.2.3 From 4df964780fe57b8cc121cf382d25ab7cf72c4c17 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Wed, 4 May 2016 17:39:28 -0700 Subject: Reworked python health checking and added tests --- src/python/grpcio/tests/health_check/__init__.py | 28 +++++ .../tests/health_check/_health_servicer_test.py | 75 ++++++++++++ src/python/grpcio/tests/tests.json | 5 +- src/python/grpcio_health_checking/.gitignore | 5 + src/python/grpcio_health_checking/commands.py | 84 -------------- src/python/grpcio_health_checking/grpc/__init__.py | 30 ----- .../grpcio_health_checking/grpc/health/__init__.py | 30 ----- .../grpc/health/v1/__init__.py | 30 ----- .../grpc/health/v1/health.proto | 49 -------- .../grpc/health/v1/health.py | 129 --------------------- .../grpc_health_checking/__init__.py | 30 +++++ .../grpc_health_checking/health/__init__.py | 30 +++++ .../grpc_health_checking/health/v1/__init__.py | 30 +++++ .../grpc_health_checking/health/v1/health.py | 66 +++++++++++ .../grpcio_health_checking/health_commands.py | 114 ++++++++++++++++++ src/python/grpcio_health_checking/setup.py | 12 +- tools/run_tests/build_python.sh | 4 + tools/run_tests/run_tests.py | 21 ++-- 18 files changed, 401 insertions(+), 371 deletions(-) create mode 100644 src/python/grpcio/tests/health_check/__init__.py create mode 100644 src/python/grpcio/tests/health_check/_health_servicer_test.py create mode 100644 src/python/grpcio_health_checking/.gitignore delete mode 100644 src/python/grpcio_health_checking/commands.py delete mode 100644 src/python/grpcio_health_checking/grpc/__init__.py delete mode 100644 src/python/grpcio_health_checking/grpc/health/__init__.py delete mode 100644 src/python/grpcio_health_checking/grpc/health/v1/__init__.py delete mode 100644 src/python/grpcio_health_checking/grpc/health/v1/health.proto delete mode 100644 src/python/grpcio_health_checking/grpc/health/v1/health.py create mode 100644 src/python/grpcio_health_checking/grpc_health_checking/__init__.py create mode 100644 src/python/grpcio_health_checking/grpc_health_checking/health/__init__.py create mode 100644 src/python/grpcio_health_checking/grpc_health_checking/health/v1/__init__.py create mode 100644 src/python/grpcio_health_checking/grpc_health_checking/health/v1/health.py create mode 100644 src/python/grpcio_health_checking/health_commands.py (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/tests/health_check/__init__.py b/src/python/grpcio/tests/health_check/__init__.py new file mode 100644 index 0000000000..100a624dc9 --- /dev/null +++ b/src/python/grpcio/tests/health_check/__init__.py @@ -0,0 +1,28 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/python/grpcio/tests/health_check/_health_servicer_test.py b/src/python/grpcio/tests/health_check/_health_servicer_test.py new file mode 100644 index 0000000000..625cb7fc59 --- /dev/null +++ b/src/python/grpcio/tests/health_check/_health_servicer_test.py @@ -0,0 +1,75 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Tests of grpc_health_checking.health.v1.health.""" + +import unittest + +from grpc_health_checking.health.v1 import health +from grpc_health_checking.health.v1 import health_pb2 + + +class HealthServicerTest(unittest.TestCase): + + def setUp(self): + self.servicer = health.HealthServicer() + self.servicer.set('', health_pb2.HealthCheckResponse.SERVING) + self.servicer.set('grpc.test.TestServiceServing', + health_pb2.HealthCheckResponse.SERVING) + self.servicer.set('grpc.test.TestServiceUnknown', + health_pb2.HealthCheckResponse.UNKNOWN) + self.servicer.set('grpc.test.TestServiceNotServing', + health_pb2.HealthCheckResponse.NOT_SERVING) + + def test_empty_service(self): + request = health_pb2.HealthCheckRequest() + resp = self.servicer.Check(request, None) + self.assertEqual(resp.status, health_pb2.HealthCheckResponse.SERVING) + + def test_serving_service(self): + request = health_pb2.HealthCheckRequest( + service='grpc.test.TestServiceServing') + resp = self.servicer.Check(request, None) + self.assertEqual(resp.status, health_pb2.HealthCheckResponse.SERVING) + + def test_unknown_serivce(self): + request = health_pb2.HealthCheckRequest( + service='grpc.test.TestServiceUnknown') + resp = self.servicer.Check(request, None) + self.assertEqual(resp.status, health_pb2.HealthCheckResponse.UNKNOWN) + + def test_not_serving_service(self): + request = health_pb2.HealthCheckRequest( + service='grpc.test.TestServiceNotServing') + resp = self.servicer.Check(request, None) + self.assertEqual(resp.status, health_pb2.HealthCheckResponse.NOT_SERVING) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/src/python/grpcio/tests/tests.json b/src/python/grpcio/tests/tests.json index 84870aaa5c..691062f25a 100644 --- a/src/python/grpcio/tests/tests.json +++ b/src/python/grpcio/tests/tests.json @@ -28,7 +28,8 @@ "_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest", "_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest", "_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest", - "_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest", + "_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest", + "_health_servicer_test.HealthServicerTest", "_implementations_test.ChannelCredentialsTest", "_insecure_interop_test.InsecureInteropTest", "_intermediary_low_test.CancellationTest", @@ -50,4 +51,4 @@ "cygrpc_test.InsecureServerInsecureClient", "cygrpc_test.SecureServerSecureClient", "cygrpc_test.TypeSmokeTest" -] \ No newline at end of file +] diff --git a/src/python/grpcio_health_checking/.gitignore b/src/python/grpcio_health_checking/.gitignore new file mode 100644 index 0000000000..85af466886 --- /dev/null +++ b/src/python/grpcio_health_checking/.gitignore @@ -0,0 +1,5 @@ +*.proto +*_pb2.py +build/ +grpcio_health_checking.egg-info/ +dist/ diff --git a/src/python/grpcio_health_checking/commands.py b/src/python/grpcio_health_checking/commands.py deleted file mode 100644 index 3f4ea6e22f..0000000000 --- a/src/python/grpcio_health_checking/commands.py +++ /dev/null @@ -1,84 +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. - -"""Provides distutils command classes for the GRPC Python setup process.""" - -import distutils -import glob -import os -import os.path -import subprocess -import sys - -import setuptools -from setuptools.command import build_py - - -class BuildProtoModules(setuptools.Command): - """Command to generate project *_pb2.py modules from proto files.""" - - description = '' - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - self.protoc_command = distutils.spawn.find_executable('protoc') - self.grpc_python_plugin_command = distutils.spawn.find_executable( - 'grpc_python_plugin') - - def run(self): - paths = [] - root_directory = os.getcwd() - for walk_root, directories, filenames in os.walk(root_directory): - for filename in filenames: - if filename.endswith('.proto'): - paths.append(os.path.join(walk_root, filename)) - command = [ - self.protoc_command, - '--plugin=protoc-gen-python-grpc={}'.format( - self.grpc_python_plugin_command), - '-I {}'.format(root_directory), - '--python_out={}'.format(root_directory), - '--python-grpc_out={}'.format(root_directory), - ] + paths - try: - subprocess.check_output(' '.join(command), cwd=root_directory, shell=True, - stderr=subprocess.STDOUT) - except subprocess.CalledProcessError as e: - raise Exception('{}\nOutput:\n{}'.format(e.message, e.output)) - - -class BuildPy(build_py.build_py): - """Custom project build command.""" - - def run(self): - self.run_command('build_proto_modules') - build_py.build_py.run(self) diff --git a/src/python/grpcio_health_checking/grpc/__init__.py b/src/python/grpcio_health_checking/grpc/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_health_checking/grpc/__init__.py +++ /dev/null @@ -1,30 +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. - - diff --git a/src/python/grpcio_health_checking/grpc/health/__init__.py b/src/python/grpcio_health_checking/grpc/health/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_health_checking/grpc/health/__init__.py +++ /dev/null @@ -1,30 +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. - - diff --git a/src/python/grpcio_health_checking/grpc/health/v1/__init__.py b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_health_checking/grpc/health/v1/__init__.py +++ /dev/null @@ -1,30 +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. - - diff --git a/src/python/grpcio_health_checking/grpc/health/v1/health.proto b/src/python/grpcio_health_checking/grpc/health/v1/health.proto deleted file mode 100644 index b0bac54be9..0000000000 --- a/src/python/grpcio_health_checking/grpc/health/v1/health.proto +++ /dev/null @@ -1,49 +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. - -syntax = "proto3"; - -package grpc.health.v1; - -message HealthCheckRequest { - string service = 1; -} - -message HealthCheckResponse { - enum ServingStatus { - UNKNOWN = 0; - SERVING = 1; - NOT_SERVING = 2; - } - ServingStatus status = 1; -} - -service Health { - rpc Check(HealthCheckRequest) returns (HealthCheckResponse); -} diff --git a/src/python/grpcio_health_checking/grpc/health/v1/health.py b/src/python/grpcio_health_checking/grpc/health/v1/health.py deleted file mode 100644 index 4b5af15aa6..0000000000 --- a/src/python/grpcio_health_checking/grpc/health/v1/health.py +++ /dev/null @@ -1,129 +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. - -"""Reference implementation for health checking in gRPC Python.""" - -import abc -import enum -import threading - -from grpc.health.v1 import health_pb2 - - -@enum.unique -class HealthStatus(enum.Enum): - """Statuses for a service mirroring the reference health.proto's values.""" - UNKNOWN = health_pb2.HealthCheckResponse.UNKNOWN - SERVING = health_pb2.HealthCheckResponse.SERVING - NOT_SERVING = health_pb2.HealthCheckResponse.NOT_SERVING - - -class _HealthServicer(health_pb2.EarlyAdopterHealthServicer): - """Servicer handling RPCs for service statuses.""" - - def __init__(self): - self._server_status_lock = threading.Lock() - self._server_status = {} - - def Check(self, request, context): - with self._server_status_lock: - if request.service not in self._server_status: - # TODO(atash): once the Python API has a way of setting the server - # status, bring us into conformance with the health check spec by - # returning the NOT_FOUND status here. - raise NotImplementedError() - else: - return health_pb2.HealthCheckResponse( - status=self._server_status[request.service].value) - - def set(service, status): - if not isinstance(status, HealthStatus): - raise TypeError('expected grpc.health.v1.health.HealthStatus ' - 'for argument `status` but got {}'.format(status)) - with self._server_status_lock: - self._server_status[service] = status - - -class HealthServer(health_pb2.EarlyAdopterHealthServer): - """Interface for the reference gRPC Python health server.""" - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def start(self): - raise NotImplementedError() - - @abc.abstractmethod - def stop(self): - raise NotImplementedError() - - @abc.abstractmethod - def set(self, service, status): - """Set the status of the given service. - - Args: - service (str): service name of the service to set the reported status of - status (HealthStatus): status to set for the specified service - """ - raise NotImplementedError() - - -class _HealthServerImplementation(HealthServer): - """Implementation for the reference gRPC Python health server.""" - - def __init__(self, server, servicer): - self._server = server - self._servicer = servicer - - def start(self): - self._server.start() - - def stop(self): - self._server.stop() - - def set(self, service, status): - self._servicer.set(service, status) - - -def create_Health_server(port, private_key=None, certificate_chain=None): - """Get a HealthServer instance. - - Args: - port (int): port number passed through to health_pb2 server creation - routine. - private_key (str): to-be-created server's desired private key - certificate_chain (str): to-be-created server's desired certificate chain - - Returns: - An instance of HealthServer (conforming thus to - EarlyAdopterHealthServer and providing a method to set server status).""" - servicer = _HealthServicer() - server = health_pb2.early_adopter_create_Health_server( - servicer, port=port, private_key=private_key, - certificate_chain=certificate_chain) - return _HealthServerImplementation(server, servicer) diff --git a/src/python/grpcio_health_checking/grpc_health_checking/__init__.py b/src/python/grpcio_health_checking/grpc_health_checking/__init__.py new file mode 100644 index 0000000000..7086519106 --- /dev/null +++ b/src/python/grpcio_health_checking/grpc_health_checking/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + diff --git a/src/python/grpcio_health_checking/grpc_health_checking/health/__init__.py b/src/python/grpcio_health_checking/grpc_health_checking/health/__init__.py new file mode 100644 index 0000000000..7086519106 --- /dev/null +++ b/src/python/grpcio_health_checking/grpc_health_checking/health/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + diff --git a/src/python/grpcio_health_checking/grpc_health_checking/health/v1/__init__.py b/src/python/grpcio_health_checking/grpc_health_checking/health/v1/__init__.py new file mode 100644 index 0000000000..7086519106 --- /dev/null +++ b/src/python/grpcio_health_checking/grpc_health_checking/health/v1/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + diff --git a/src/python/grpcio_health_checking/grpc_health_checking/health/v1/health.py b/src/python/grpcio_health_checking/grpc_health_checking/health/v1/health.py new file mode 100644 index 0000000000..7068ba9605 --- /dev/null +++ b/src/python/grpcio_health_checking/grpc_health_checking/health/v1/health.py @@ -0,0 +1,66 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Reference implementation for health checking in gRPC Python.""" + +import threading + +from grpc_health_checking.health.v1 import health_pb2 + + +class HealthServicer(health_pb2.BetaHealthServicer): + """Servicer handling RPCs for service statuses.""" + + def __init__(self): + self._server_status_lock = threading.Lock() + self._server_status = {} + + def Check(self, request, context): + with self._server_status_lock: + if request.service not in self._server_status: + # TODO(atash): once the Python API has a way of setting the server + # status, bring us into conformance with the health check spec by + # returning the NOT_FOUND status here. + raise NotImplementedError() + else: + return health_pb2.HealthCheckResponse( + status=self._server_status[request.service]) + + def set(self, service, status): + """Sets the status of a service. + + Args: + service: string, the name of the service. + NOTE, '' must be set. + status: HealthCheckResponse.status enum value indicating + the status of the service + """ + with self._server_status_lock: + self._server_status[service] = status + diff --git a/src/python/grpcio_health_checking/health_commands.py b/src/python/grpcio_health_checking/health_commands.py new file mode 100644 index 0000000000..b01e0bd0e8 --- /dev/null +++ b/src/python/grpcio_health_checking/health_commands.py @@ -0,0 +1,114 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Provides distutils command classes for the GRPC Python setup process.""" + +import distutils +import glob +import os +import os.path +import shutil +import subprocess +import sys + +import setuptools +from setuptools.command import build_py +from setuptools.command import sdist + +ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) +HEALTH_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/health/v1/health.proto') + + +class BuildProtoModules(setuptools.Command): + """Command to generate project *_pb2.py modules from proto files.""" + + description = '' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + self.protoc_command = distutils.spawn.find_executable('protoc') + self.grpc_python_plugin_command = distutils.spawn.find_executable( + 'grpc_python_plugin') + + def run(self): + paths = [] + root_directory = os.getcwd() + for walk_root, directories, filenames in os.walk(root_directory): + for filename in filenames: + if filename.endswith('.proto'): + paths.append(os.path.join(walk_root, filename)) + command = [ + self.protoc_command, + '--plugin=protoc-gen-python-grpc={}'.format( + self.grpc_python_plugin_command), + '-I {}'.format(root_directory), + '--python_out={}'.format(root_directory), + '--python-grpc_out={}'.format(root_directory), + ] + paths + try: + subprocess.check_output(' '.join(command), cwd=root_directory, shell=True, + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + raise Exception('{}\nOutput:\n{}'.format(e.message, e.output)) + + +class CopyProtoModules(setuptools.Command): + """Command to copy proto modules from grpc/src/proto.""" + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + if os.path.isfile(HEALTH_PROTO): + shutil.copyfile( + HEALTH_PROTO, + os.path.join(ROOT_DIR, 'grpc_health_checking/health/v1/health.proto')) + + +class BuildPy(build_py.build_py): + """Custom project build command.""" + + def run(self): + self.run_command('copy_proto_modules') + self.run_command('build_proto_modules') + build_py.build_py.run(self) + + +class SDist(sdist.sdist): + """Custom project build command.""" + + def run(self): + self.run_command('copy_proto_modules') + sdist.sdist.run(self) diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py index 35253ba312..5aa4bb8845 100644 --- a/src/python/grpcio_health_checking/setup.py +++ b/src/python/grpcio_health_checking/setup.py @@ -40,7 +40,7 @@ import setuptools os.chdir(os.path.dirname(os.path.abspath(__file__))) # Break import-style to ensure we can actually find our commands module. -import commands +import health_commands _PACKAGES = ( setuptools.find_packages('.') @@ -51,19 +51,21 @@ _PACKAGE_DIRECTORIES = { } _INSTALL_REQUIRES = ( - 'grpcio>=0.11.0b0', + 'grpcio>=grpcio-0.14.0.dev0', ) _SETUP_REQUIRES = _INSTALL_REQUIRES _COMMAND_CLASS = { - 'build_proto_modules': commands.BuildProtoModules, - 'build_py': commands.BuildPy, + 'copy_proto_modules': health_commands.CopyProtoModules, + 'build_proto_modules': health_commands.BuildProtoModules, + 'build_py': health_commands.BuildPy, + 'sdist': health_commands.SDist, } setuptools.setup( name='grpcio_health_checking', - version='0.11.0b0', + version='0.14.0b1', packages=list(_PACKAGES), package_dir=_PACKAGE_DIRECTORIES, install_requires=_INSTALL_REQUIRES, diff --git a/tools/run_tests/build_python.sh b/tools/run_tests/build_python.sh index 594c20b14c..4cc6881ef5 100755 --- a/tools/run_tests/build_python.sh +++ b/tools/run_tests/build_python.sh @@ -55,3 +55,7 @@ $ROOT/.tox/${TOX_PYTHON_ENV}/bin/python $ROOT/setup.py build $ROOT/.tox/${TOX_PYTHON_ENV}/bin/python $ROOT/setup.py build_py $ROOT/.tox/${TOX_PYTHON_ENV}/bin/python $ROOT/setup.py build_ext --inplace $ROOT/.tox/${TOX_PYTHON_ENV}/bin/python $ROOT/setup.py gather --test + +# Build the health checker +$ROOT/.tox/${TOX_PYTHON_ENV}/bin/python $ROOT/src/python/grpcio_health_checking/setup.py build +$ROOT/.tox/${TOX_PYTHON_ENV}/bin/python $ROOT/src/python/grpcio_health_checking/setup.py build_py diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 37291f4d3f..9c6d91ba7e 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -272,17 +272,12 @@ class NodeLanguage(object): def __init__(self): self.platform = platform_string() + self.node_version = '0.12' def configure(self, config, args): self.config = config self.args = args - _check_compiler(self.args.compiler, ['default', 'node0.12', - 'node4', 'node5']) - if self.args.compiler == 'default': - self.node_version = '4' - else: - # Take off the word "node" - self.node_version = self.args.compiler[4:] + _check_compiler(self.args.compiler, ['default']) def test_specs(self): if self.platform == 'windows': @@ -371,7 +366,10 @@ class PythonLanguage(object): with open('src/python/grpcio/tests/tests.json') as tests_json_file: tests_json = json.load(tests_json_file) environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS) - environment['PYTHONPATH'] = os.path.abspath('src/python/gens') + environment['PYTHONPATH'] = '{}:{}'.format( + os.path.abspath('src/python/gens'), + os.path.abspath('src/python/grpcio_health_checking')) + if self.config.build_config != 'gcov': return [self.config.job_spec( ['tools/run_tests/run_python.sh', self._tox_env], @@ -807,8 +805,7 @@ argp.add_argument('--compiler', 'gcc4.4', 'gcc4.9', 'gcc5.3', 'clang3.4', 'clang3.6', 'vs2010', 'vs2013', 'vs2015', - 'python2.7', 'python3.4', - 'node0.12', 'node4', 'node5'], + 'python2.7', 'python3.4'], default='default', help='Selects compiler to use. Allowed values depend on the platform and language.') argp.add_argument('--build_only', @@ -912,13 +909,13 @@ if args.use_docker: env = os.environ.copy() env['RUN_TESTS_COMMAND'] = run_tests_cmd env['DOCKERFILE_DIR'] = dockerfile_dir - env['DOCKER_RUN_SCRIPT'] = 'tools/run_tests/dockerize/docker_run_tests.sh' + env['DOCKER_RUN_SCRIPT'] = 'tools/jenkins/docker_run_tests.sh' if args.xml_report: env['XML_REPORT'] = args.xml_report if not args.travis: env['TTY_FLAG'] = '-t' # enables Ctrl-C when not on Jenkins. - subprocess.check_call(['tools/run_tests/dockerize/build_docker_and_run_tests.sh'], + subprocess.check_call(['tools/jenkins/build_docker_and_run_tests.sh'], shell=True, env=env) sys.exit(0) -- cgit v1.2.3 From 7809f2b78a5abf3ecb2ade16f3be907388c559e8 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Thu, 5 May 2016 20:38:42 +0000 Subject: Raise parallelism in grpc._cython._channel_test The underlying bug in Core that this test was written to isolate was fixed weeks ago. --- src/python/grpcio/tests/unit/_cython/_channel_test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/tests/unit/_cython/_channel_test.py b/src/python/grpcio/tests/unit/_cython/_channel_test.py index b414f8e6f6..931cd9083e 100644 --- a/src/python/grpcio/tests/unit/_cython/_channel_test.py +++ b/src/python/grpcio/tests/unit/_cython/_channel_test.py @@ -33,8 +33,7 @@ import unittest from grpc._cython import cygrpc -# TODO(nathaniel): This should be at least one hundred. Why not one thousand? -_PARALLELISM = 4 +from tests.unit.framework.common import test_constants def _channel_and_completion_queue(): @@ -61,7 +60,7 @@ def _create_loop_destroy(): def _in_parallel(behavior, arguments): threads = tuple( threading.Thread(target=behavior, args=arguments) - for _ in range(_PARALLELISM)) + for _ in range(test_constants.PARALLELISM)) for thread in threads: thread.start() for thread in threads: -- cgit v1.2.3 From 253a7109ed1c86df0e482e899bc952e36bdc9f42 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Fri, 6 May 2016 03:00:51 +0200 Subject: The release branch is now 0.14.0-pre1. --- Makefile | 2 +- build.yaml | 2 +- package.json | 2 +- src/core/lib/surface/version.c | 2 +- src/csharp/Grpc.Core/VersionInfo.cs | 2 +- src/csharp/build_packages.bat | 2 +- src/node/tools/package.json | 2 +- src/python/grpcio/grpc_version.py | 2 +- src/ruby/lib/grpc/version.rb | 2 +- src/ruby/tools/version.rb | 2 +- tools/distrib/python/grpcio_tools/grpc_version.py | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- tools/doxygen/Doxyfile.core | 2 +- tools/doxygen/Doxyfile.core.internal | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/python/grpcio') diff --git a/Makefile b/Makefile index e77aa2dd16..635df30c20 100644 --- a/Makefile +++ b/Makefile @@ -407,7 +407,7 @@ E = @echo Q = @ endif -VERSION = 0.14.0-dev +VERSION = 0.14.0-pre1 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/build.yaml b/build.yaml index 1a0888bdc3..7a74e73c72 100644 --- a/build.yaml +++ b/build.yaml @@ -7,7 +7,7 @@ settings: '#3': Use "-preN" suffixes to identify pre-release versions '#4': Per-language overrides are possible with (eg) ruby_version tag here '#5': See the expand_version.py for all the quirks here - version: 0.14.0-dev + version: 0.14.0-pre1 filegroups: - name: census public_headers: diff --git a/package.json b/package.json index 5ed7f363d3..b22cfc1f93 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "0.14.0-dev", + "version": "0.14.0-pre1", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "http://www.grpc.io/", diff --git a/src/core/lib/surface/version.c b/src/core/lib/surface/version.c index fe954cbefb..0f4b1111f4 100644 --- a/src/core/lib/surface/version.c +++ b/src/core/lib/surface/version.c @@ -36,4 +36,4 @@ #include -const char *grpc_version_string(void) { return "0.14.0-dev"; } +const char *grpc_version_string(void) { return "0.14.0-pre1"; } diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index f7a9cb9c1c..70ce9a18df 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -53,6 +53,6 @@ namespace Grpc.Core /// /// Current version of gRPC C# /// - public const string CurrentVersion = "0.14.0-dev"; + public const string CurrentVersion = "0.14.0-pre1"; } } diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index 9a60be26b6..9c7b877fea 100644 --- a/src/csharp/build_packages.bat +++ b/src/csharp/build_packages.bat @@ -1,7 +1,7 @@ @rem Builds gRPC NuGet packages @rem Current package versions -set VERSION=0.14.0-dev +set VERSION=0.14.0-pre1 set PROTOBUF_VERSION=3.0.0-beta2 @rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well. diff --git a/src/node/tools/package.json b/src/node/tools/package.json index d98ed0b1fc..9bca5eab6f 100644 --- a/src/node/tools/package.json +++ b/src/node/tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "0.14.0-dev", + "version": "0.14.0-pre1", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "http://www.grpc.io/", diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 873b4e2a91..87fadf9a97 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION='0.14.0.dev0' +VERSION='0.14.0rc1' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 67c6a5d5a1..5117c85cea 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -29,5 +29,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '0.14.0.dev' + VERSION = '0.14.0.pre1' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 12ad21b80e..ec085d2655 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -29,6 +29,6 @@ module GRPC module Tools - VERSION = '0.14.0.dev' + VERSION = '0.14.0.pre1' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index b8ae8e20b8..ee522a0bc3 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION='0.14.0.dev0' +VERSION='0.14.0rc1' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 664ca03d97..f58f7e7281 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0-dev +PROJECT_NUMBER = 0.14.0-pre1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 5188ef1e8d..a7a17bac3f 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0-dev +PROJECT_NUMBER = 0.14.0-pre1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 84b5c2a8ef..d1259e7aee 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0-dev +PROJECT_NUMBER = 0.14.0-pre1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 228c1d98d8..6b7a8be861 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0-dev +PROJECT_NUMBER = 0.14.0-pre1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a -- cgit v1.2.3 From 16caa50aae7d1669550be35e205039f65cc4c363 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Fri, 6 May 2016 03:02:51 +0200 Subject: Master is now 0.15.0-dev. --- Makefile | 2 +- build.yaml | 2 +- composer.json | 2 +- package.json | 2 +- package.xml | 8 ++++---- src/core/lib/surface/version.c | 2 +- src/csharp/Grpc.Core/VersionInfo.cs | 4 ++-- src/csharp/build_packages.bat | 2 +- src/node/tools/package.json | 2 +- src/python/grpcio/grpc_version.py | 2 +- src/ruby/lib/grpc/version.rb | 2 +- src/ruby/tools/version.rb | 2 +- tools/distrib/python/grpcio_tools/grpc_version.py | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- tools/doxygen/Doxyfile.core | 2 +- tools/doxygen/Doxyfile.core.internal | 2 +- 17 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src/python/grpcio') diff --git a/Makefile b/Makefile index e77aa2dd16..a684ea8611 100644 --- a/Makefile +++ b/Makefile @@ -407,7 +407,7 @@ E = @echo Q = @ endif -VERSION = 0.14.0-dev +VERSION = 0.15.0-dev CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/build.yaml b/build.yaml index 1a0888bdc3..13916830c1 100644 --- a/build.yaml +++ b/build.yaml @@ -7,7 +7,7 @@ settings: '#3': Use "-preN" suffixes to identify pre-release versions '#4': Per-language overrides are possible with (eg) ruby_version tag here '#5': See the expand_version.py for all the quirks here - version: 0.14.0-dev + version: 0.15.0-dev filegroups: - name: census public_headers: diff --git a/composer.json b/composer.json index 97b1a5cb49..b77a59e351 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc", "type": "library", "description": "gRPC library for PHP", - "version": "0.14.0", + "version": "0.15.0", "keywords": ["rpc"], "homepage": "http://grpc.io", "license": "BSD-3-Clause", diff --git a/package.json b/package.json index 5ed7f363d3..54a44ca551 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "0.14.0-dev", + "version": "0.15.0-dev", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "http://www.grpc.io/", diff --git a/package.xml b/package.xml index 716d6ed289..152d5d6190 100644 --- a/package.xml +++ b/package.xml @@ -13,8 +13,8 @@ 2016-04-19 - 0.14.0 - 0.14.0 + 0.15.0 + 0.15.0 beta @@ -1054,8 +1054,8 @@ Update to wrap gRPC C Core version 0.10.0 - 0.14.0 - 0.14.0 + 0.15.0 + 0.15.0 beta diff --git a/src/core/lib/surface/version.c b/src/core/lib/surface/version.c index fe954cbefb..aca76d2bb7 100644 --- a/src/core/lib/surface/version.c +++ b/src/core/lib/surface/version.c @@ -36,4 +36,4 @@ #include -const char *grpc_version_string(void) { return "0.14.0-dev"; } +const char *grpc_version_string(void) { return "0.15.0-dev"; } diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index f7a9cb9c1c..e1609341d9 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -48,11 +48,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "0.14.0.0"; + public const string CurrentAssemblyFileVersion = "0.15.0.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "0.14.0-dev"; + public const string CurrentVersion = "0.15.0-dev"; } } diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index 9a60be26b6..7520b0f81a 100644 --- a/src/csharp/build_packages.bat +++ b/src/csharp/build_packages.bat @@ -1,7 +1,7 @@ @rem Builds gRPC NuGet packages @rem Current package versions -set VERSION=0.14.0-dev +set VERSION=0.15.0-dev set PROTOBUF_VERSION=3.0.0-beta2 @rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well. diff --git a/src/node/tools/package.json b/src/node/tools/package.json index d98ed0b1fc..efdfa81124 100644 --- a/src/node/tools/package.json +++ b/src/node/tools/package.json @@ -1,6 +1,6 @@ { "name": "grpc-tools", - "version": "0.14.0-dev", + "version": "0.15.0-dev", "author": "Google Inc.", "description": "Tools for developing with gRPC on Node.js", "homepage": "http://www.grpc.io/", diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 873b4e2a91..0c13104d9d 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION='0.14.0.dev0' +VERSION='0.15.0.dev0' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 67c6a5d5a1..01c8c5ac8f 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -29,5 +29,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '0.14.0.dev' + VERSION = '0.15.0.dev' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 12ad21b80e..dca7fd7e72 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -29,6 +29,6 @@ module GRPC module Tools - VERSION = '0.14.0.dev' + VERSION = '0.15.0.dev' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index b8ae8e20b8..1267d0e45d 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -29,4 +29,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION='0.14.0.dev0' +VERSION='0.15.0.dev0' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 664ca03d97..2a319db979 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0-dev +PROJECT_NUMBER = 0.15.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 5188ef1e8d..5fdfafbf3e 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0-dev +PROJECT_NUMBER = 0.15.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 84b5c2a8ef..aabca410da 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0-dev +PROJECT_NUMBER = 0.15.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 228c1d98d8..3ffc6174ed 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0-dev +PROJECT_NUMBER = 0.15.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a -- cgit v1.2.3 From ab5309c9b12aef6fd874b5f925ea04df4eebde14 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Thu, 5 May 2016 18:39:01 -0700 Subject: Remove precompiled Python extension hack --- setup.py | 42 +++++++-------- src/python/grpcio/precompiled.py | 114 --------------------------------------- 2 files changed, 18 insertions(+), 138 deletions(-) delete mode 100644 src/python/grpcio/precompiled.py (limited to 'src/python/grpcio') diff --git a/setup.py b/setup.py index 5cd26124f6..f96824fa88 100644 --- a/setup.py +++ b/setup.py @@ -54,7 +54,6 @@ sys.path.insert(0, os.path.abspath(PYTHON_STEM)) # Break import-style to ensure we can actually find our in-repo dependencies. import commands -import precompiled import grpc_core_dependencies import grpc_version @@ -173,7 +172,6 @@ COMMAND_CLASS = { 'build_project_metadata': commands.BuildProjectMetadata, 'build_py': commands.BuildPy, 'build_ext': commands.BuildExt, - 'build_tagged_ext': precompiled.BuildTaggedExt, 'gather': commands.Gather, 'run_interop': commands.RunInterop, 'test_lite': commands.TestLite @@ -229,25 +227,21 @@ else: PACKAGES = setuptools.find_packages( PYTHON_STEM, exclude=['tests', 'tests.*']) -setup_arguments = { - 'name': 'grpcio', - 'version': grpc_version.VERSION, - 'license': LICENSE, - 'ext_modules': CYTHON_EXTENSION_MODULES, - 'packages': list(PACKAGES), - 'package_dir': PACKAGE_DIRECTORIES, - # TODO(atash): Figure out why auditwheel doesn't like namespace packages. - #'namespace_packages': ['grpc'], - 'package_data': PACKAGE_DATA, - 'install_requires': INSTALL_REQUIRES, - 'setup_requires': SETUP_REQUIRES, - 'cmdclass': COMMAND_CLASS, - 'tests_require': TESTS_REQUIRE, - 'test_suite': TEST_SUITE, - 'test_loader': TEST_LOADER, - 'test_runner': TEST_RUNNER, -} - -precompiled.update_setup_arguments(setup_arguments) - -setuptools.setup(**setup_arguments) +setuptools.setup( + name='grpcio', + version=grpc_version.VERSION, + license=LICENSE, + ext_modules=CYTHON_EXTENSION_MODULES, + packages=list(PACKAGES), + package_dir=PACKAGE_DIRECTORIES, + # TODO(atash): Figure out why auditwheel doesn't like namespace packages. + #namespace_packages=['grpc'], + package_data=PACKAGE_DATA, + install_requires=INSTALL_REQUIRES, + setup_requires=SETUP_REQUIRES, + cmdclass=COMMAND_CLASS, + tests_require=TESTS_REQUIRE, + test_suite=TEST_SUITE, + test_loader=TEST_LOADER, + test_runner=TEST_RUNNER, +) diff --git a/src/python/grpcio/precompiled.py b/src/python/grpcio/precompiled.py deleted file mode 100644 index b6aa7fc90e..0000000000 --- a/src/python/grpcio/precompiled.py +++ /dev/null @@ -1,114 +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. - -import os -import platform -import shutil -import sys -import sysconfig - -import setuptools - -import commands -import grpc_version - -try: - from urllib2 import urlopen -except ImportError: - from urllib.request import urlopen - -PYTHON_STEM = os.path.dirname(os.path.abspath(__file__)) -BINARIES_REPOSITORY = os.environ.get( - 'GRPC_PYTHON_BINARIES_REPOSITORY', - 'https://storage.googleapis.com/grpc-precompiled-binaries/python') -USE_PRECOMPILED_BINARIES = bool(int(os.environ.get( - 'GRPC_PYTHON_USE_PRECOMPILED_BINARIES', '1'))) - -def _tagged_ext_name(base): - uname = platform.uname() - tags = ( - grpc_version.VERSION, - 'py{}'.format(sysconfig.get_python_version()), - uname[0], - uname[4], - ) - ucs = 'ucs{}'.format(sysconfig.get_config_var('Py_UNICODE_SIZE')) - return '{base}-{tags}-{ucs}'.format( - base=base, tags='-'.join(tags), ucs=ucs) - - -class BuildTaggedExt(setuptools.Command): - - description = 'build the gRPC tagged extensions' - user_options = [] - - def initialize_options(self): - # distutils requires this override. - pass - - def finalize_options(self): - # distutils requires this override. - pass - - def run(self): - if 'linux' in sys.platform: - self.run_command('build_ext') - try: - os.makedirs('dist/') - except OSError: - pass - shutil.copyfile( - os.path.join(PYTHON_STEM, 'grpc/_cython/cygrpc.so'), - 'dist/{}.so'.format(_tagged_ext_name('cygrpc'))) - else: - sys.stderr.write('nothing to do for build_tagged_ext\n') - - -def update_setup_arguments(setup_arguments): - if not USE_PRECOMPILED_BINARIES: - sys.stderr.write('not using precompiled extension') - return - url = '{}/{}.so'.format(BINARIES_REPOSITORY, _tagged_ext_name('cygrpc')) - target_path = os.path.join(PYTHON_STEM, 'grpc/_cython/cygrpc.so') - try: - extension = urlopen(url).read() - except: - sys.stderr.write( - 'could not download precompiled extension: {}\n'.format(url)) - return - try: - with open(target_path, 'w') as target: - target.write(extension) - setup_arguments['ext_modules'] = [] - except: - sys.stderr.write( - 'could not write precompiled extension to directory: {} -> {}\n' - .format(url, target_path)) - return - setup_arguments['package_data']['grpc._cython'].append('cygrpc.so') -- cgit v1.2.3 From 0bdc7ccab9622cd2e62eec6007bff3391bc664f4 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Thu, 5 May 2016 19:03:43 -0700 Subject: Fix #4592 Adds a command that allows the instructions to be used to install gRPC Python from scratch. --- src/python/grpcio/README.rst | 1 + 1 file changed, 1 insertion(+) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/README.rst b/src/python/grpcio/README.rst index cb3f6b87fe..afc4fe6a37 100644 --- a/src/python/grpcio/README.rst +++ b/src/python/grpcio/README.rst @@ -48,6 +48,7 @@ package named :code:`python-dev`). $ export REPO_ROOT=grpc # REPO_ROOT can be any directory of your choice $ git clone https://github.com/grpc/grpc.git $REPO_ROOT $ cd $REPO_ROOT + $ git submodule update --init # For the next two commands do `sudo pip install` if you get permission-denied errors $ pip install -rrequirements.txt -- cgit v1.2.3 From af1fe578e099f5e470a9e1a853181983753ceefa Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Fri, 6 May 2016 09:40:52 -0700 Subject: Namespace change --- .../tests/health_check/_health_servicer_test.py | 6 +- src/python/grpcio_health_checking/MANIFEST.in | 2 + .../grpcio_health_checking/grpc_health/__init__.py | 30 ++++++++++ .../grpc_health/health/__init__.py | 30 ++++++++++ .../grpc_health/health/v1/__init__.py | 30 ++++++++++ .../grpc_health/health/v1/health.py | 66 ++++++++++++++++++++++ .../grpc_health_checking/__init__.py | 30 ---------- .../grpc_health_checking/health/__init__.py | 30 ---------- .../grpc_health_checking/health/v1/__init__.py | 30 ---------- .../grpc_health_checking/health/v1/health.py | 66 ---------------------- .../grpcio_health_checking/health_commands.py | 2 +- src/python/grpcio_health_checking/setup.py | 2 +- 12 files changed, 163 insertions(+), 161 deletions(-) create mode 100644 src/python/grpcio_health_checking/grpc_health/__init__.py create mode 100644 src/python/grpcio_health_checking/grpc_health/health/__init__.py create mode 100644 src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py create mode 100644 src/python/grpcio_health_checking/grpc_health/health/v1/health.py delete mode 100644 src/python/grpcio_health_checking/grpc_health_checking/__init__.py delete mode 100644 src/python/grpcio_health_checking/grpc_health_checking/health/__init__.py delete mode 100644 src/python/grpcio_health_checking/grpc_health_checking/health/v1/__init__.py delete mode 100644 src/python/grpcio_health_checking/grpc_health_checking/health/v1/health.py (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/tests/health_check/_health_servicer_test.py b/src/python/grpcio/tests/health_check/_health_servicer_test.py index 625cb7fc59..1b63388663 100644 --- a/src/python/grpcio/tests/health_check/_health_servicer_test.py +++ b/src/python/grpcio/tests/health_check/_health_servicer_test.py @@ -27,12 +27,12 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Tests of grpc_health_checking.health.v1.health.""" +"""Tests of grpc_health.health.v1.health.""" import unittest -from grpc_health_checking.health.v1 import health -from grpc_health_checking.health.v1 import health_pb2 +from grpc_health.health.v1 import health +from grpc_health.health.v1 import health_pb2 class HealthServicerTest(unittest.TestCase): diff --git a/src/python/grpcio_health_checking/MANIFEST.in b/src/python/grpcio_health_checking/MANIFEST.in index 40c6ac8497..7d26647697 100644 --- a/src/python/grpcio_health_checking/MANIFEST.in +++ b/src/python/grpcio_health_checking/MANIFEST.in @@ -1 +1,3 @@ +include health_commands.py +graft grpc_health global-exclude *.pyc diff --git a/src/python/grpcio_health_checking/grpc_health/__init__.py b/src/python/grpcio_health_checking/grpc_health/__init__.py new file mode 100644 index 0000000000..7086519106 --- /dev/null +++ b/src/python/grpcio_health_checking/grpc_health/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + diff --git a/src/python/grpcio_health_checking/grpc_health/health/__init__.py b/src/python/grpcio_health_checking/grpc_health/health/__init__.py new file mode 100644 index 0000000000..7086519106 --- /dev/null +++ b/src/python/grpcio_health_checking/grpc_health/health/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + diff --git a/src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py b/src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py new file mode 100644 index 0000000000..7086519106 --- /dev/null +++ b/src/python/grpcio_health_checking/grpc_health/health/v1/__init__.py @@ -0,0 +1,30 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + diff --git a/src/python/grpcio_health_checking/grpc_health/health/v1/health.py b/src/python/grpcio_health_checking/grpc_health/health/v1/health.py new file mode 100644 index 0000000000..8da60c70cb --- /dev/null +++ b/src/python/grpcio_health_checking/grpc_health/health/v1/health.py @@ -0,0 +1,66 @@ +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Reference implementation for health checking in gRPC Python.""" + +import threading + +from grpc_health.health.v1 import health_pb2 + + +class HealthServicer(health_pb2.BetaHealthServicer): + """Servicer handling RPCs for service statuses.""" + + def __init__(self): + self._server_status_lock = threading.Lock() + self._server_status = {} + + def Check(self, request, context): + with self._server_status_lock: + if request.service not in self._server_status: + # TODO(atash): once the Python API has a way of setting the server + # status, bring us into conformance with the health check spec by + # returning the NOT_FOUND status here. + raise NotImplementedError() + else: + return health_pb2.HealthCheckResponse( + status=self._server_status[request.service]) + + def set(self, service, status): + """Sets the status of a service. + + Args: + service: string, the name of the service. + NOTE, '' must be set. + status: HealthCheckResponse.status enum value indicating + the status of the service + """ + with self._server_status_lock: + self._server_status[service] = status + diff --git a/src/python/grpcio_health_checking/grpc_health_checking/__init__.py b/src/python/grpcio_health_checking/grpc_health_checking/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_health_checking/grpc_health_checking/__init__.py +++ /dev/null @@ -1,30 +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. - - diff --git a/src/python/grpcio_health_checking/grpc_health_checking/health/__init__.py b/src/python/grpcio_health_checking/grpc_health_checking/health/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_health_checking/grpc_health_checking/health/__init__.py +++ /dev/null @@ -1,30 +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. - - diff --git a/src/python/grpcio_health_checking/grpc_health_checking/health/v1/__init__.py b/src/python/grpcio_health_checking/grpc_health_checking/health/v1/__init__.py deleted file mode 100644 index 7086519106..0000000000 --- a/src/python/grpcio_health_checking/grpc_health_checking/health/v1/__init__.py +++ /dev/null @@ -1,30 +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. - - diff --git a/src/python/grpcio_health_checking/grpc_health_checking/health/v1/health.py b/src/python/grpcio_health_checking/grpc_health_checking/health/v1/health.py deleted file mode 100644 index 7068ba9605..0000000000 --- a/src/python/grpcio_health_checking/grpc_health_checking/health/v1/health.py +++ /dev/null @@ -1,66 +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. - -"""Reference implementation for health checking in gRPC Python.""" - -import threading - -from grpc_health_checking.health.v1 import health_pb2 - - -class HealthServicer(health_pb2.BetaHealthServicer): - """Servicer handling RPCs for service statuses.""" - - def __init__(self): - self._server_status_lock = threading.Lock() - self._server_status = {} - - def Check(self, request, context): - with self._server_status_lock: - if request.service not in self._server_status: - # TODO(atash): once the Python API has a way of setting the server - # status, bring us into conformance with the health check spec by - # returning the NOT_FOUND status here. - raise NotImplementedError() - else: - return health_pb2.HealthCheckResponse( - status=self._server_status[request.service]) - - def set(self, service, status): - """Sets the status of a service. - - Args: - service: string, the name of the service. - NOTE, '' must be set. - status: HealthCheckResponse.status enum value indicating - the status of the service - """ - with self._server_status_lock: - self._server_status[service] = status - diff --git a/src/python/grpcio_health_checking/health_commands.py b/src/python/grpcio_health_checking/health_commands.py index b01e0bd0e8..631066f331 100644 --- a/src/python/grpcio_health_checking/health_commands.py +++ b/src/python/grpcio_health_checking/health_commands.py @@ -94,7 +94,7 @@ class CopyProtoModules(setuptools.Command): if os.path.isfile(HEALTH_PROTO): shutil.copyfile( HEALTH_PROTO, - os.path.join(ROOT_DIR, 'grpc_health_checking/health/v1/health.proto')) + os.path.join(ROOT_DIR, 'grpc_health/health/v1/health.proto')) class BuildPy(build_py.build_py): diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py index 2818c5b81d..d68a7ced8e 100644 --- a/src/python/grpcio_health_checking/setup.py +++ b/src/python/grpcio_health_checking/setup.py @@ -63,7 +63,7 @@ _COMMAND_CLASS = { setuptools.setup( name='grpcio_health_checking', - version='0.14.0b1', + version='0.14.0b0', packages=list(_PACKAGES), package_dir=_PACKAGE_DIRECTORIES, install_requires=_INSTALL_REQUIRES, -- cgit v1.2.3 From f6cedf82c30c9329e06d8b93c6ef28b7f2ad7e3a Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Thu, 5 May 2016 16:50:49 -0700 Subject: Made complex directories for python protoc test --- .../tests/protoc_plugin/beta_python_plugin_test.py | 295 +++++++++++---------- .../tests/protoc_plugin/protoc_plugin_test.proto | 139 ---------- .../protos/payload/test_payload.proto | 51 ++++ .../protos/requests/r/test_requests.proto | 77 ++++++ .../protos/responses/test_responses.proto | 47 ++++ .../protos/service/test_service.proto | 64 +++++ 6 files changed, 392 insertions(+), 281 deletions(-) delete mode 100644 src/python/grpcio/tests/protoc_plugin/protoc_plugin_test.proto create mode 100644 src/python/grpcio/tests/protoc_plugin/protos/payload/test_payload.proto create mode 100644 src/python/grpcio/tests/protoc_plugin/protos/requests/r/test_requests.proto create mode 100644 src/python/grpcio/tests/protoc_plugin/protos/responses/test_responses.proto create mode 100644 src/python/grpcio/tests/protoc_plugin/protos/service/test_service.proto (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py b/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py index 3dc3042e38..7466f88059 100644 --- a/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py +++ b/src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py @@ -59,11 +59,12 @@ STUB_FACTORY_IDENTIFIER = 'beta_create_TestService_stub' class _ServicerMethods(object): - def __init__(self, test_pb2): + def __init__(self, response_pb2, payload_pb2): self._condition = threading.Condition() self._paused = False self._fail = False - self._test_pb2 = test_pb2 + self._response_pb2 = response_pb2 + self._payload_pb2 = payload_pb2 @contextlib.contextmanager def pause(self): # pylint: disable=invalid-name @@ -90,22 +91,22 @@ class _ServicerMethods(object): self._condition.wait() def UnaryCall(self, request, unused_rpc_context): - response = self._test_pb2.SimpleResponse() - response.payload.payload_type = self._test_pb2.COMPRESSABLE + response = self._response_pb2.SimpleResponse() + response.payload.payload_type = self._payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * request.response_size self._control() return response def StreamingOutputCall(self, request, unused_rpc_context): for parameter in request.response_parameters: - response = self._test_pb2.StreamingOutputCallResponse() - response.payload.payload_type = self._test_pb2.COMPRESSABLE + response = self._response_pb2.StreamingOutputCallResponse() + response.payload.payload_type = self._payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * parameter.size self._control() yield response def StreamingInputCall(self, request_iter, unused_rpc_context): - response = self._test_pb2.StreamingInputCallResponse() + response = self._response_pb2.StreamingInputCallResponse() aggregated_payload_size = 0 for request in request_iter: aggregated_payload_size += len(request.payload.payload_compressable) @@ -116,8 +117,8 @@ class _ServicerMethods(object): def FullDuplexCall(self, request_iter, unused_rpc_context): for request in request_iter: for parameter in request.response_parameters: - response = self._test_pb2.StreamingOutputCallResponse() - response.payload.payload_type = self._test_pb2.COMPRESSABLE + response = self._response_pb2.StreamingOutputCallResponse() + response.payload.payload_type = self._payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * parameter.size self._control() yield response @@ -126,8 +127,8 @@ class _ServicerMethods(object): responses = [] for request in request_iter: for parameter in request.response_parameters: - response = self._test_pb2.StreamingOutputCallResponse() - response.payload.payload_type = self._test_pb2.COMPRESSABLE + response = self._response_pb2.StreamingOutputCallResponse() + response.payload.payload_type = self._payload_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * parameter.size self._control() responses.append(response) @@ -136,23 +137,25 @@ class _ServicerMethods(object): @contextlib.contextmanager -def _CreateService(test_pb2): +def _CreateService(service_pb2, response_pb2, payload_pb2): """Provides a servicer backend and a stub. The servicer is just the implementation of the actual servicer passed to the face player of the python RPC implementation; the two are detached. Args: - test_pb2: The test_pb2 module generated by this test. + service_pb2: The service_pb2 module generated by this test. + response_pb2: The response_pb2 module generated by this test + payload_pb2: The payload_pb2 module generated by this test Yields: A (servicer_methods, stub) pair where servicer_methods is the back-end of the service bound to the stub and and stub is the stub on which to invoke RPCs. """ - servicer_methods = _ServicerMethods(test_pb2) + servicer_methods = _ServicerMethods(response_pb2, payload_pb2) - class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)): + class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): def UnaryCall(self, request, context): return servicer_methods.UnaryCall(request, context) @@ -170,55 +173,52 @@ def _CreateService(test_pb2): return servicer_methods.HalfDuplexCall(request_iter, context) servicer = Servicer() - server = getattr(test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) + server = getattr(service_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) port = server.add_insecure_port('[::]:0') server.start() channel = implementations.insecure_channel('localhost', port) - stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)(channel) - yield servicer_methods, stub + stub = getattr(service_pb2, STUB_FACTORY_IDENTIFIER)(channel) + yield (servicer_methods, stub) server.stop(0) @contextlib.contextmanager -def _CreateIncompleteService(test_pb2): +def _CreateIncompleteService(service_pb2): """Provides a servicer backend that fails to implement methods and its stub. The servicer is just the implementation of the actual servicer passed to the face player of the python RPC implementation; the two are detached. - Args: - test_pb2: The test_pb2 module generated by this test. - + service_pb2: The service_pb2 module generated by this test. Yields: A (servicer_methods, stub) pair where servicer_methods is the back-end of the service bound to the stub and and stub is the stub on which to invoke RPCs. """ - servicer_methods = _ServicerMethods(test_pb2) - class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)): + class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): pass servicer = Servicer() - server = getattr(test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) + server = getattr(service_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) port = server.add_insecure_port('[::]:0') server.start() channel = implementations.insecure_channel('localhost', port) - stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)(channel) - yield servicer_methods, stub + stub = getattr(service_pb2, STUB_FACTORY_IDENTIFIER)(channel) + yield None, stub server.stop(0) -def _streaming_input_request_iterator(test_pb2): +def _streaming_input_request_iterator(request_pb2, payload_pb2): for _ in range(3): - request = test_pb2.StreamingInputCallRequest() - request.payload.payload_type = test_pb2.COMPRESSABLE + request = request_pb2.StreamingInputCallRequest() + request.payload.payload_type = payload_pb2.COMPRESSABLE request.payload.payload_compressable = 'a' yield request -def _streaming_output_request(test_pb2): - request = test_pb2.StreamingOutputCallRequest() +def _streaming_output_request(request_pb2): + request = request_pb2.StreamingOutputCallRequest() sizes = [1, 2, 3] request.response_parameters.add(size=sizes[0], interval_us=0) request.response_parameters.add(size=sizes[1], interval_us=0) @@ -226,11 +226,11 @@ def _streaming_output_request(test_pb2): return request -def _full_duplex_request_iterator(test_pb2): - request = test_pb2.StreamingOutputCallRequest() +def _full_duplex_request_iterator(request_pb2): + request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=1, interval_us=0) yield request - request = test_pb2.StreamingOutputCallRequest() + request = request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=2, interval_us=0) request.response_parameters.add(size=3, interval_us=0) yield request @@ -250,8 +250,6 @@ class PythonPluginTest(unittest.TestCase): protoc_command = 'protoc' protoc_plugin_filename = distutils.spawn.find_executable( 'grpc_python_plugin') - test_proto_filename = pkg_resources.resource_filename( - 'tests.protoc_plugin', 'protoc_plugin_test.proto') if not os.path.isfile(protoc_command): # Assume that if we haven't built protoc that it's on the system. protoc_command = 'protoc' @@ -259,19 +257,44 @@ class PythonPluginTest(unittest.TestCase): # Ensure that the output directory exists. self.outdir = tempfile.mkdtemp() + # Find all proto files + paths = [] + root_dir = os.path.dirname(os.path.realpath(__file__)) + proto_dir = os.path.join(root_dir, 'protos') + for walk_root, _, filenames in os.walk(proto_dir): + for filename in filenames: + if filename.endswith('.proto'): + path = os.path.join(walk_root, filename) + paths.append(path) + # Invoke protoc with the plugin. cmd = [ protoc_command, '--plugin=protoc-gen-python-grpc=%s' % protoc_plugin_filename, - '-I .', + '-I %s' % root_dir, '--python_out=%s' % self.outdir, - '--python-grpc_out=%s' % self.outdir, - os.path.basename(test_proto_filename), - ] + '--python-grpc_out=%s' % self.outdir + ] + paths subprocess.check_call(' '.join(cmd), shell=True, env=os.environ, - cwd=os.path.dirname(test_proto_filename)) + cwd=os.path.dirname(os.path.realpath(__file__))) + + # Generated proto directories dont include __init__.py, but + # these are needed for python package resolution + for walk_root, _, _ in os.walk(os.path.join(self.outdir, 'protos')): + path = os.path.join(walk_root, '__init__.py') + open(path, 'a').close() + sys.path.insert(0, self.outdir) + import protos.payload.test_payload_pb2 as payload_pb2 # pylint: disable=g-import-not-at-top + import protos.requests.r.test_requests_pb2 as request_pb2 # pylint: disable=g-import-not-at-top + import protos.responses.test_responses_pb2 as response_pb2 # pylint: disable=g-import-not-at-top + import protos.service.test_service_pb2 as service_pb2 # pylint: disable=g-import-not-at-top + self._payload_pb2 = payload_pb2 + self._request_pb2 = request_pb2 + self._response_pb2 = response_pb2 + self._service_pb2 = service_pb2 + def tearDown(self): try: shutil.rmtree(self.outdir) @@ -282,43 +305,40 @@ class PythonPluginTest(unittest.TestCase): def testImportAttributes(self): # check that we can access the generated module and its members. - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - self.assertIsNotNone(getattr(test_pb2, SERVICER_IDENTIFIER, None)) - self.assertIsNotNone(getattr(test_pb2, STUB_IDENTIFIER, None)) - self.assertIsNotNone(getattr(test_pb2, SERVER_FACTORY_IDENTIFIER, None)) - self.assertIsNotNone(getattr(test_pb2, STUB_FACTORY_IDENTIFIER, None)) + self.assertIsNotNone( + getattr(self._service_pb2, SERVICER_IDENTIFIER, None)) + self.assertIsNotNone( + getattr(self._service_pb2, STUB_IDENTIFIER, None)) + self.assertIsNotNone( + getattr(self._service_pb2, SERVER_FACTORY_IDENTIFIER, None)) + self.assertIsNotNone( + getattr(self._service_pb2, STUB_FACTORY_IDENTIFIER, None)) def testUpDown(self): - import protoc_plugin_test_pb2 as test_pb2 - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (servicer, stub): - request = test_pb2.SimpleRequest(response_size=13) + with _CreateService( + self._service_pb2, self._response_pb2, self._payload_pb2): + self._request_pb2.SimpleRequest(response_size=13) def testIncompleteServicer(self): - import protoc_plugin_test_pb2 as test_pb2 - moves.reload_module(test_pb2) - with _CreateIncompleteService(test_pb2) as (servicer, stub): - request = test_pb2.SimpleRequest(response_size=13) + with _CreateIncompleteService(self._service_pb2) as (_, stub): + request = self._request_pb2.SimpleRequest(response_size=13) try: - response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT) + stub.UnaryCall(request, test_constants.LONG_TIMEOUT) except face.AbortionError as error: self.assertEqual(interfaces.StatusCode.UNIMPLEMENTED, error.code) def testUnaryCall(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (methods, stub): - request = test_pb2.SimpleRequest(response_size=13) + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): + request = self._request_pb2.SimpleRequest(response_size=13) response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT) expected_response = methods.UnaryCall(request, 'not a real context!') self.assertEqual(expected_response, response) def testUnaryCallFuture(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - request = test_pb2.SimpleRequest(response_size=13) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): + request = self._request_pb2.SimpleRequest(response_size=13) # Check that the call does not block waiting for the server to respond. with methods.pause(): response_future = stub.UnaryCall.future( @@ -328,10 +348,9 @@ class PythonPluginTest(unittest.TestCase): self.assertEqual(expected_response, response) def testUnaryCallFutureExpired(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (methods, stub): - request = test_pb2.SimpleRequest(response_size=13) + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): + request = self._request_pb2.SimpleRequest(response_size=13) with methods.pause(): response_future = stub.UnaryCall.future( request, test_constants.SHORT_TIMEOUT) @@ -339,30 +358,27 @@ class PythonPluginTest(unittest.TestCase): response_future.result() def testUnaryCallFutureCancelled(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - request = test_pb2.SimpleRequest(response_size=13) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): + request = self._request_pb2.SimpleRequest(response_size=13) with methods.pause(): response_future = stub.UnaryCall.future(request, 1) response_future.cancel() self.assertTrue(response_future.cancelled()) def testUnaryCallFutureFailed(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - request = test_pb2.SimpleRequest(response_size=13) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): + request = self._request_pb2.SimpleRequest(response_size=13) with methods.fail(): response_future = stub.UnaryCall.future( request, test_constants.LONG_TIMEOUT) self.assertIsNotNone(response_future.exception()) def testStreamingOutputCall(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - request = _streaming_output_request(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): + request = _streaming_output_request(self._request_pb2) responses = stub.StreamingOutputCall( request, test_constants.LONG_TIMEOUT) expected_responses = methods.StreamingOutputCall( @@ -372,10 +388,9 @@ class PythonPluginTest(unittest.TestCase): self.assertEqual(expected_response, response) def testStreamingOutputCallExpired(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - request = _streaming_output_request(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): + request = _streaming_output_request(self._request_pb2) with methods.pause(): responses = stub.StreamingOutputCall( request, test_constants.SHORT_TIMEOUT) @@ -383,10 +398,9 @@ class PythonPluginTest(unittest.TestCase): list(responses) def testStreamingOutputCallCancelled(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - request = _streaming_output_request(test_pb2) - with _CreateService(test_pb2) as (unused_methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): + request = _streaming_output_request(self._request_pb2) responses = stub.StreamingOutputCall( request, test_constants.LONG_TIMEOUT) next(responses) @@ -395,10 +409,9 @@ class PythonPluginTest(unittest.TestCase): next(responses) def testStreamingOutputCallFailed(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - request = _streaming_output_request(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): + request = _streaming_output_request(self._request_pb2) with methods.fail(): responses = stub.StreamingOutputCall(request, 1) self.assertIsNotNone(responses) @@ -406,36 +419,38 @@ class PythonPluginTest(unittest.TestCase): next(responses) def testStreamingInputCall(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): response = stub.StreamingInputCall( - _streaming_input_request_iterator(test_pb2), + _streaming_input_request_iterator( + self._request_pb2, self._payload_pb2), test_constants.LONG_TIMEOUT) expected_response = methods.StreamingInputCall( - _streaming_input_request_iterator(test_pb2), 'not a real RpcContext!') + _streaming_input_request_iterator(self._request_pb2, self._payload_pb2), + 'not a real RpcContext!') self.assertEqual(expected_response, response) def testStreamingInputCallFuture(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): with methods.pause(): response_future = stub.StreamingInputCall.future( - _streaming_input_request_iterator(test_pb2), + _streaming_input_request_iterator( + self._request_pb2, self._payload_pb2), test_constants.LONG_TIMEOUT) response = response_future.result() expected_response = methods.StreamingInputCall( - _streaming_input_request_iterator(test_pb2), 'not a real RpcContext!') + _streaming_input_request_iterator(self._request_pb2, self._payload_pb2), + 'not a real RpcContext!') self.assertEqual(expected_response, response) def testStreamingInputCallFutureExpired(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): with methods.pause(): response_future = stub.StreamingInputCall.future( - _streaming_input_request_iterator(test_pb2), + _streaming_input_request_iterator( + self._request_pb2, self._payload_pb2), test_constants.SHORT_TIMEOUT) with self.assertRaises(face.ExpirationError): response_future.result() @@ -443,12 +458,12 @@ class PythonPluginTest(unittest.TestCase): response_future.exception(), face.ExpirationError) def testStreamingInputCallFutureCancelled(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): with methods.pause(): response_future = stub.StreamingInputCall.future( - _streaming_input_request_iterator(test_pb2), + _streaming_input_request_iterator( + self._request_pb2, self._payload_pb2), test_constants.LONG_TIMEOUT) response_future.cancel() self.assertTrue(response_future.cancelled()) @@ -456,32 +471,32 @@ class PythonPluginTest(unittest.TestCase): response_future.result() def testStreamingInputCallFutureFailed(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): with methods.fail(): response_future = stub.StreamingInputCall.future( - _streaming_input_request_iterator(test_pb2), + _streaming_input_request_iterator( + self._request_pb2, self._payload_pb2), test_constants.LONG_TIMEOUT) self.assertIsNotNone(response_future.exception()) def testFullDuplexCall(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): responses = stub.FullDuplexCall( - _full_duplex_request_iterator(test_pb2), test_constants.LONG_TIMEOUT) + _full_duplex_request_iterator(self._request_pb2), + test_constants.LONG_TIMEOUT) expected_responses = methods.FullDuplexCall( - _full_duplex_request_iterator(test_pb2), 'not a real RpcContext!') + _full_duplex_request_iterator(self._request_pb2), + 'not a real RpcContext!') for expected_response, response in moves.zip_longest( expected_responses, responses): self.assertEqual(expected_response, response) def testFullDuplexCallExpired(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - request_iterator = _full_duplex_request_iterator(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + request_iterator = _full_duplex_request_iterator(self._request_pb2) + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): with methods.pause(): responses = stub.FullDuplexCall( request_iterator, test_constants.SHORT_TIMEOUT) @@ -489,10 +504,9 @@ class PythonPluginTest(unittest.TestCase): list(responses) def testFullDuplexCallCancelled(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (methods, stub): - request_iterator = _full_duplex_request_iterator(test_pb2) + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): + request_iterator = _full_duplex_request_iterator(self._request_pb2) responses = stub.FullDuplexCall( request_iterator, test_constants.LONG_TIMEOUT) next(responses) @@ -501,10 +515,9 @@ class PythonPluginTest(unittest.TestCase): next(responses) def testFullDuplexCallFailed(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - request_iterator = _full_duplex_request_iterator(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + request_iterator = _full_duplex_request_iterator(self._request_pb2) + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): with methods.fail(): responses = stub.FullDuplexCall( request_iterator, test_constants.LONG_TIMEOUT) @@ -513,14 +526,13 @@ class PythonPluginTest(unittest.TestCase): next(responses) def testHalfDuplexCall(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): def half_duplex_request_iterator(): - request = test_pb2.StreamingOutputCallRequest() + request = self._request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=1, interval_us=0) yield request - request = test_pb2.StreamingOutputCallRequest() + request = self._request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=2, interval_us=0) request.response_parameters.add(size=3, interval_us=0) yield request @@ -533,8 +545,6 @@ class PythonPluginTest(unittest.TestCase): self.assertEqual(expected_response, response) def testHalfDuplexCallWedged(self): - import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top - moves.reload_module(test_pb2) condition = threading.Condition() wait_cell = [False] @contextlib.contextmanager @@ -547,13 +557,14 @@ class PythonPluginTest(unittest.TestCase): wait_cell[0] = False condition.notify_all() def half_duplex_request_iterator(): - request = test_pb2.StreamingOutputCallRequest() + request = self._request_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=1, interval_us=0) yield request with condition: while wait_cell[0]: condition.wait() - with _CreateService(test_pb2) as (methods, stub): + with _CreateService(self._service_pb2, self._response_pb2, + self._payload_pb2) as (methods, stub): with wait(): responses = stub.HalfDuplexCall( half_duplex_request_iterator(), test_constants.SHORT_TIMEOUT) @@ -563,5 +574,5 @@ class PythonPluginTest(unittest.TestCase): if __name__ == '__main__': - os.chdir(os.path.dirname(sys.argv[0])) + #os.chdir(os.path.dirname(sys.argv[0])) unittest.main(verbosity=2) diff --git a/src/python/grpcio/tests/protoc_plugin/protoc_plugin_test.proto b/src/python/grpcio/tests/protoc_plugin/protoc_plugin_test.proto deleted file mode 100644 index 6762a8e7f3..0000000000 --- a/src/python/grpcio/tests/protoc_plugin/protoc_plugin_test.proto +++ /dev/null @@ -1,139 +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. - -// An integration test service that covers all the method signature permutations -// of unary/streaming requests/responses. -// This file is duplicated around the code base. See GitHub issue #526. -syntax = "proto2"; - -package grpc_protoc_plugin; - -enum PayloadType { - // Compressable text format. - COMPRESSABLE= 1; - - // Uncompressable binary format. - UNCOMPRESSABLE = 2; - - // Randomly chosen from all other formats defined in this enum. - RANDOM = 3; -} - -message Payload { - required PayloadType payload_type = 1; - oneof payload_body { - string payload_compressable = 2; - bytes payload_uncompressable = 3; - } -} - -message SimpleRequest { - // Desired payload type in the response from the server. - // If response_type is RANDOM, server randomly chooses one from other formats. - optional PayloadType response_type = 1 [default=COMPRESSABLE]; - - // Desired payload size in the response from the server. - // If response_type is COMPRESSABLE, this denotes the size before compression. - optional int32 response_size = 2; - - // Optional input payload sent along with the request. - optional Payload payload = 3; -} - -message SimpleResponse { - optional Payload payload = 1; -} - -message StreamingInputCallRequest { - // Optional input payload sent along with the request. - optional Payload payload = 1; - - // Not expecting any payload from the response. -} - -message StreamingInputCallResponse { - // Aggregated size of payloads received from the client. - optional int32 aggregated_payload_size = 1; -} - -message ResponseParameters { - // Desired payload sizes in responses from the server. - // If response_type is COMPRESSABLE, this denotes the size before compression. - required int32 size = 1; - - // Desired interval between consecutive responses in the response stream in - // microseconds. - required int32 interval_us = 2; -} - -message StreamingOutputCallRequest { - // Desired payload type in the response from the server. - // If response_type is RANDOM, the payload from each response in the stream - // might be of different types. This is to simulate a mixed type of payload - // stream. - optional PayloadType response_type = 1 [default=COMPRESSABLE]; - - repeated ResponseParameters response_parameters = 2; - - // Optional input payload sent along with the request. - optional Payload payload = 3; -} - -message StreamingOutputCallResponse { - optional Payload payload = 1; -} - -service TestService { - // One request followed by one response. - // The server returns the client payload as-is. - rpc UnaryCall(SimpleRequest) returns (SimpleResponse); - - // One request followed by a sequence of responses (streamed download). - // The server returns the payload with client desired type and sizes. - rpc StreamingOutputCall(StreamingOutputCallRequest) - returns (stream StreamingOutputCallResponse); - - // A sequence of requests followed by one response (streamed upload). - // The server returns the aggregated size of client payload as the result. - rpc StreamingInputCall(stream StreamingInputCallRequest) - returns (StreamingInputCallResponse); - - // A sequence of requests with each request served by the server immediately. - // As one request could lead to multiple responses, this interface - // demonstrates the idea of full duplexing. - rpc FullDuplexCall(stream StreamingOutputCallRequest) - returns (stream StreamingOutputCallResponse); - - // A sequence of requests followed by a sequence of responses. - // The server buffers all the client requests and then serves them in order. A - // stream of responses are returned to the client when the server starts with - // first request. - rpc HalfDuplexCall(stream StreamingOutputCallRequest) - returns (stream StreamingOutputCallResponse); -} diff --git a/src/python/grpcio/tests/protoc_plugin/protos/payload/test_payload.proto b/src/python/grpcio/tests/protoc_plugin/protos/payload/test_payload.proto new file mode 100644 index 0000000000..457543aa79 --- /dev/null +++ b/src/python/grpcio/tests/protoc_plugin/protos/payload/test_payload.proto @@ -0,0 +1,51 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package grpc_protoc_plugin; + +enum PayloadType { + // Compressable text format. + COMPRESSABLE= 0; + + // Uncompressable binary format. + UNCOMPRESSABLE = 1; + + // Randomly chosen from all other formats defined in this enum. + RANDOM = 2; +} + +message Payload { + PayloadType payload_type = 1; + oneof payload_body { + string payload_compressable = 2; + bytes payload_uncompressable = 3; + } +} diff --git a/src/python/grpcio/tests/protoc_plugin/protos/requests/r/test_requests.proto b/src/python/grpcio/tests/protoc_plugin/protos/requests/r/test_requests.proto new file mode 100644 index 0000000000..54105df6a5 --- /dev/null +++ b/src/python/grpcio/tests/protoc_plugin/protos/requests/r/test_requests.proto @@ -0,0 +1,77 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +import "protos/payload/test_payload.proto"; + +package grpc_protoc_plugin; + +message SimpleRequest { + // Desired payload type in the response from the server. + // If response_type is RANDOM, server randomly chooses one from other formats. + PayloadType response_type = 1; + + // Desired payload size in the response from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + int32 response_size = 2; + + // input payload sent along with the request. + Payload payload = 3; +} + +message StreamingInputCallRequest { + // input payload sent along with the request. + Payload payload = 1; + + // Not expecting any payload from the response. +} + +message ResponseParameters { + // Desired payload sizes in responses from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + int32 size = 1; + + // Desired interval between consecutive responses in the response stream in + // microseconds. + int32 interval_us = 2; +} + +message StreamingOutputCallRequest { + // Desired payload type in the response from the server. + // If response_type is RANDOM, the payload from each response in the stream + // might be of different types. This is to simulate a mixed type of payload + // stream. + PayloadType response_type = 1; + + repeated ResponseParameters response_parameters = 2; + + // input payload sent along with the request. + Payload payload = 3; +} diff --git a/src/python/grpcio/tests/protoc_plugin/protos/responses/test_responses.proto b/src/python/grpcio/tests/protoc_plugin/protos/responses/test_responses.proto new file mode 100644 index 0000000000..734fbda86e --- /dev/null +++ b/src/python/grpcio/tests/protoc_plugin/protos/responses/test_responses.proto @@ -0,0 +1,47 @@ +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +import "protos/payload/test_payload.proto"; + +package grpc_protoc_plugin; + +message SimpleResponse { + Payload payload = 1; +} + +message StreamingInputCallResponse { + // Aggregated size of payloads received from the client. + int32 aggregated_payload_size = 1; +} + +message StreamingOutputCallResponse { + Payload payload = 1; +} diff --git a/src/python/grpcio/tests/protoc_plugin/protos/service/test_service.proto b/src/python/grpcio/tests/protoc_plugin/protos/service/test_service.proto new file mode 100644 index 0000000000..fe715ee7f9 --- /dev/null +++ b/src/python/grpcio/tests/protoc_plugin/protos/service/test_service.proto @@ -0,0 +1,64 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +import "protos/requests/r/test_requests.proto"; +import "protos/responses/test_responses.proto"; + +package grpc_protoc_plugin; + +service TestService { + // One request followed by one response. + // The server returns the client payload as-is. + rpc UnaryCall(SimpleRequest) returns (SimpleResponse); + + // One request followed by a sequence of responses (streamed download). + // The server returns the payload with client desired type and sizes. + rpc StreamingOutputCall(StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // A sequence of requests followed by one response (streamed upload). + // The server returns the aggregated size of client payload as the result. + rpc StreamingInputCall(stream StreamingInputCallRequest) + returns (StreamingInputCallResponse); + + // A sequence of requests with each request served by the server immediately. + // As one request could lead to multiple responses, this interface + // demonstrates the idea of full duplexing. + rpc FullDuplexCall(stream StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // A sequence of requests followed by a sequence of responses. + // The server buffers all the client requests and then serves them in order. A + // stream of responses are returned to the client when the server starts with + // first request. + rpc HalfDuplexCall(stream StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); +} -- cgit v1.2.3 From 42342cbebb55ee168252accb0433b1bb6cc8e4a7 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 9 May 2016 08:12:35 -0700 Subject: Revert "cronet wrapper code" --- BUILD | 80 --- Makefile | 7 - binding.gyp | 3 - build.yaml | 59 -- config.m4 | 5 - gRPC.podspec | 76 --- grpc.def | 1 - grpc.gemspec | 40 -- include/grpc/grpc_cronet.h | 51 -- package.xml | 40 -- .../cronet/client/secure/cronet_channel_create.c | 69 --- .../transport/cronet/transport/cronet_api_dummy.c | 85 --- .../transport/cronet/transport/cronet_transport.c | 640 --------------------- src/python/grpcio/grpc/_cython/imports.generated.c | 2 - src/python/grpcio/grpc/_cython/imports.generated.h | 4 - src/python/grpcio/grpc_core_dependencies.py | 3 - src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 - src/ruby/ext/grpc/rb_grpc_imports.generated.h | 4 - test/core/surface/public_headers_must_be_c89.c | 1 - third_party/objective_c/Cronet/cronet_c_for_grpc.h | 202 ------- tools/doxygen/Doxyfile.core | 1 - tools/doxygen/Doxyfile.core.internal | 40 -- tools/run_tests/sources_and_headers.json | 120 +--- vsprojects/vcxproj/grpc/grpc.vcxproj | 43 -- vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 144 ----- 25 files changed, 1 insertion(+), 1721 deletions(-) delete mode 100644 include/grpc/grpc_cronet.h delete mode 100644 src/core/ext/transport/cronet/client/secure/cronet_channel_create.c delete mode 100644 src/core/ext/transport/cronet/transport/cronet_api_dummy.c delete mode 100644 src/core/ext/transport/cronet/transport/cronet_transport.c delete mode 100644 third_party/objective_c/Cronet/cronet_c_for_grpc.h (limited to 'src/python/grpcio') diff --git a/BUILD b/BUILD index fae3596eec..1da1650438 100644 --- a/BUILD +++ b/BUILD @@ -285,42 +285,6 @@ cc_library( "src/core/ext/client_config/subchannel_call_holder.h", "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", - "include/grpc/byte_buffer.h", - "include/grpc/grpc.h", - "include/grpc/impl/codegen/alloc.h", - "include/grpc/impl/codegen/atm.h", - "include/grpc/impl/codegen/atm_gcc_atomic.h", - "include/grpc/impl/codegen/atm_gcc_sync.h", - "include/grpc/impl/codegen/atm_win32.h", - "include/grpc/impl/codegen/byte_buffer.h", - "include/grpc/impl/codegen/compression_types.h", - "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/grpc_types.h", - "include/grpc/impl/codegen/log.h", - "include/grpc/impl/codegen/port_platform.h", - "include/grpc/impl/codegen/propagation_bits.h", - "include/grpc/impl/codegen/slice.h", - "include/grpc/impl/codegen/slice_buffer.h", - "include/grpc/impl/codegen/status.h", - "include/grpc/impl/codegen/sync.h", - "include/grpc/impl/codegen/sync_generic.h", - "include/grpc/impl/codegen/sync_posix.h", - "include/grpc/impl/codegen/sync_win32.h", - "include/grpc/impl/codegen/time.h", - "include/grpc/status.h", - "include/grpc/support/alloc.h", - "include/grpc/support/atm.h", - "include/grpc/support/host_port.h", - "include/grpc/support/log.h", - "include/grpc/support/port_platform.h", - "include/grpc/support/slice.h", - "include/grpc/support/slice_buffer.h", - "include/grpc/support/string_util.h", - "include/grpc/support/sync.h", - "include/grpc/support/time.h", - "include/grpc/support/useful.h", - "src/core/lib/support/string.h", - "third_party/objective_c/Cronet/cronet_c_for_grpc.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", "src/core/ext/census/aggregation.h", @@ -475,9 +439,6 @@ cc_library( "src/core/ext/client_config/uri_parser.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", - "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", - "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", - "src/core/ext/transport/cronet/transport/cronet_transport.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", @@ -522,7 +483,6 @@ cc_library( "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_win32.h", "include/grpc/impl/codegen/time.h", - "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "include/grpc/census.h", @@ -1500,9 +1460,6 @@ objc_library( "src/core/ext/client_config/uri_parser.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", - "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", - "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", - "src/core/ext/transport/cronet/transport/cronet_transport.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", @@ -1547,7 +1504,6 @@ objc_library( "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_win32.h", "include/grpc/impl/codegen/time.h", - "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "include/grpc/census.h", @@ -1675,42 +1631,6 @@ objc_library( "src/core/ext/client_config/subchannel_call_holder.h", "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", - "include/grpc/byte_buffer.h", - "include/grpc/grpc.h", - "include/grpc/impl/codegen/alloc.h", - "include/grpc/impl/codegen/atm.h", - "include/grpc/impl/codegen/atm_gcc_atomic.h", - "include/grpc/impl/codegen/atm_gcc_sync.h", - "include/grpc/impl/codegen/atm_win32.h", - "include/grpc/impl/codegen/byte_buffer.h", - "include/grpc/impl/codegen/compression_types.h", - "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/grpc_types.h", - "include/grpc/impl/codegen/log.h", - "include/grpc/impl/codegen/port_platform.h", - "include/grpc/impl/codegen/propagation_bits.h", - "include/grpc/impl/codegen/slice.h", - "include/grpc/impl/codegen/slice_buffer.h", - "include/grpc/impl/codegen/status.h", - "include/grpc/impl/codegen/sync.h", - "include/grpc/impl/codegen/sync_generic.h", - "include/grpc/impl/codegen/sync_posix.h", - "include/grpc/impl/codegen/sync_win32.h", - "include/grpc/impl/codegen/time.h", - "include/grpc/status.h", - "include/grpc/support/alloc.h", - "include/grpc/support/atm.h", - "include/grpc/support/host_port.h", - "include/grpc/support/log.h", - "include/grpc/support/port_platform.h", - "include/grpc/support/slice.h", - "include/grpc/support/slice_buffer.h", - "include/grpc/support/string_util.h", - "include/grpc/support/sync.h", - "include/grpc/support/time.h", - "include/grpc/support/useful.h", - "src/core/lib/support/string.h", - "third_party/objective_c/Cronet/cronet_c_for_grpc.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", "src/core/ext/census/aggregation.h", diff --git a/Makefile b/Makefile index a684ea8611..ffaf770144 100644 --- a/Makefile +++ b/Makefile @@ -2623,9 +2623,6 @@ LIBGRPC_SRC = \ src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ - src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ - src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -2673,7 +2670,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ - include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -14321,9 +14317,6 @@ ifneq ($(OPENSSL_DEP),) # otherwise parallel compilation will fail if a source is compiled first. src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP) -src/core/ext/transport/cronet/client/secure/cronet_channel_create.c: $(OPENSSL_DEP) -src/core/ext/transport/cronet/transport/cronet_api_dummy.c: $(OPENSSL_DEP) -src/core/ext/transport/cronet/transport/cronet_transport.c: $(OPENSSL_DEP) src/core/lib/http/httpcli_security_connector.c: $(OPENSSL_DEP) src/core/lib/security/b64.c: $(OPENSSL_DEP) src/core/lib/security/client_auth_filter.c: $(OPENSSL_DEP) diff --git a/binding.gyp b/binding.gyp index 12a745ffb0..4314ab7243 100644 --- a/binding.gyp +++ b/binding.gyp @@ -709,9 +709,6 @@ 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', - 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', - 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', - 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/build.yaml b/build.yaml index 13916830c1..5e47c08455 100644 --- a/build.yaml +++ b/build.yaml @@ -400,7 +400,6 @@ filegroups: - grpc_client_config - name: grpc_secure public_headers: - - include/grpc/grpc_cronet.h - include/grpc/grpc_security.h - include/grpc/grpc_security_constants.h headers: @@ -548,63 +547,6 @@ filegroups: - grpc_transport_chttp2 - grpc_base - grpc_secure -- name: grpc_transport_cronet_client_secure - headers: - - include/grpc/byte_buffer.h - - include/grpc/grpc.h - - include/grpc/impl/codegen/alloc.h - - include/grpc/impl/codegen/atm.h - - include/grpc/impl/codegen/atm_gcc_atomic.h - - include/grpc/impl/codegen/atm_gcc_sync.h - - include/grpc/impl/codegen/atm_win32.h - - include/grpc/impl/codegen/byte_buffer.h - - include/grpc/impl/codegen/compression_types.h - - include/grpc/impl/codegen/connectivity_state.h - - include/grpc/impl/codegen/grpc_types.h - - include/grpc/impl/codegen/log.h - - include/grpc/impl/codegen/port_platform.h - - include/grpc/impl/codegen/propagation_bits.h - - include/grpc/impl/codegen/slice.h - - include/grpc/impl/codegen/slice_buffer.h - - include/grpc/impl/codegen/status.h - - include/grpc/impl/codegen/sync.h - - include/grpc/impl/codegen/sync_generic.h - - include/grpc/impl/codegen/sync_posix.h - - include/grpc/impl/codegen/sync_win32.h - - include/grpc/impl/codegen/time.h - - include/grpc/status.h - - include/grpc/support/alloc.h - - include/grpc/support/atm.h - - include/grpc/support/host_port.h - - include/grpc/support/log.h - - include/grpc/support/port_platform.h - - include/grpc/support/slice.h - - include/grpc/support/slice_buffer.h - - include/grpc/support/string_util.h - - include/grpc/support/sync.h - - include/grpc/support/time.h - - include/grpc/support/useful.h - - src/core/ext/transport/chttp2/transport/incoming_metadata.h - - src/core/lib/channel/channel_stack.h - - src/core/lib/channel/context.h - - src/core/lib/debug/trace.h - - src/core/lib/iomgr/closure.h - - src/core/lib/iomgr/exec_ctx.h - - src/core/lib/iomgr/pollset.h - - src/core/lib/iomgr/pollset_set.h - - src/core/lib/support/string.h - - src/core/lib/surface/channel.h - - src/core/lib/surface/channel_stack_type.h - - src/core/lib/transport/byte_stream.h - - src/core/lib/transport/metadata.h - - src/core/lib/transport/metadata_batch.h - - src/core/lib/transport/transport.h - - src/core/lib/transport/transport_impl.h - - third_party/objective_c/Cronet/cronet_c_for_grpc.h - src: - - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c - - src/core/ext/transport/cronet/transport/cronet_api_dummy.c - - src/core/ext/transport/cronet/transport/cronet_transport.c - name: nanopb headers: - third_party/nanopb/pb.h @@ -792,7 +734,6 @@ libs: - grpc_transport_chttp2_client_secure - grpc_transport_chttp2_server_insecure - grpc_transport_chttp2_client_insecure - - grpc_transport_cronet_client_secure - grpc_lb_policy_grpclb - grpc_lb_policy_pick_first - grpc_lb_policy_round_robin diff --git a/config.m4 b/config.m4 index 5259e679ba..74f9ad242a 100644 --- a/config.m4 +++ b/config.m4 @@ -228,9 +228,6 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ - src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ - src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -569,8 +566,6 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/insecure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/secure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport) - PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/cronet/client/secure) - PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/cronet/transport) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/channel) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug) diff --git a/gRPC.podspec b/gRPC.podspec index 018306ca64..569f89bf7c 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -287,42 +287,6 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_call_holder.h', 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', - 'include/grpc/byte_buffer.h', - 'include/grpc/grpc.h', - 'include/grpc/impl/codegen/alloc.h', - 'include/grpc/impl/codegen/atm.h', - 'include/grpc/impl/codegen/atm_gcc_atomic.h', - 'include/grpc/impl/codegen/atm_gcc_sync.h', - 'include/grpc/impl/codegen/atm_win32.h', - 'include/grpc/impl/codegen/byte_buffer.h', - 'include/grpc/impl/codegen/compression_types.h', - 'include/grpc/impl/codegen/connectivity_state.h', - 'include/grpc/impl/codegen/grpc_types.h', - 'include/grpc/impl/codegen/log.h', - 'include/grpc/impl/codegen/port_platform.h', - 'include/grpc/impl/codegen/propagation_bits.h', - 'include/grpc/impl/codegen/slice.h', - 'include/grpc/impl/codegen/slice_buffer.h', - 'include/grpc/impl/codegen/status.h', - 'include/grpc/impl/codegen/sync.h', - 'include/grpc/impl/codegen/sync_generic.h', - 'include/grpc/impl/codegen/sync_posix.h', - 'include/grpc/impl/codegen/sync_win32.h', - 'include/grpc/impl/codegen/time.h', - 'include/grpc/status.h', - 'include/grpc/support/alloc.h', - 'include/grpc/support/atm.h', - 'include/grpc/support/host_port.h', - 'include/grpc/support/log.h', - 'include/grpc/support/port_platform.h', - 'include/grpc/support/slice.h', - 'include/grpc/support/slice_buffer.h', - 'include/grpc/support/string_util.h', - 'include/grpc/support/sync.h', - 'include/grpc/support/time.h', - 'include/grpc/support/useful.h', - 'src/core/lib/support/string.h', - 'third_party/objective_c/Cronet/cronet_c_for_grpc.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', 'third_party/nanopb/pb.h', @@ -361,7 +325,6 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/sync_posix.h', 'include/grpc/impl/codegen/sync_win32.h', 'include/grpc/impl/codegen/time.h', - 'include/grpc/grpc_cronet.h', 'include/grpc/grpc_security.h', 'include/grpc/grpc_security_constants.h', 'include/grpc/census.h', @@ -511,9 +474,6 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', - 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', - 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', - 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', @@ -670,42 +630,6 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_call_holder.h', 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', - 'include/grpc/byte_buffer.h', - 'include/grpc/grpc.h', - 'include/grpc/impl/codegen/alloc.h', - 'include/grpc/impl/codegen/atm.h', - 'include/grpc/impl/codegen/atm_gcc_atomic.h', - 'include/grpc/impl/codegen/atm_gcc_sync.h', - 'include/grpc/impl/codegen/atm_win32.h', - 'include/grpc/impl/codegen/byte_buffer.h', - 'include/grpc/impl/codegen/compression_types.h', - 'include/grpc/impl/codegen/connectivity_state.h', - 'include/grpc/impl/codegen/grpc_types.h', - 'include/grpc/impl/codegen/log.h', - 'include/grpc/impl/codegen/port_platform.h', - 'include/grpc/impl/codegen/propagation_bits.h', - 'include/grpc/impl/codegen/slice.h', - 'include/grpc/impl/codegen/slice_buffer.h', - 'include/grpc/impl/codegen/status.h', - 'include/grpc/impl/codegen/sync.h', - 'include/grpc/impl/codegen/sync_generic.h', - 'include/grpc/impl/codegen/sync_posix.h', - 'include/grpc/impl/codegen/sync_win32.h', - 'include/grpc/impl/codegen/time.h', - 'include/grpc/status.h', - 'include/grpc/support/alloc.h', - 'include/grpc/support/atm.h', - 'include/grpc/support/host_port.h', - 'include/grpc/support/log.h', - 'include/grpc/support/port_platform.h', - 'include/grpc/support/slice.h', - 'include/grpc/support/slice_buffer.h', - 'include/grpc/support/string_util.h', - 'include/grpc/support/sync.h', - 'include/grpc/support/time.h', - 'include/grpc/support/useful.h', - 'src/core/lib/support/string.h', - 'third_party/objective_c/Cronet/cronet_c_for_grpc.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', 'third_party/nanopb/pb.h', diff --git a/grpc.def b/grpc.def index 09a94a6cd0..61948ed1b8 100644 --- a/grpc.def +++ b/grpc.def @@ -87,7 +87,6 @@ EXPORTS grpc_header_nonbin_value_is_legal grpc_is_binary_header grpc_call_error_to_string - grpc_cronet_secure_channel_create grpc_auth_property_iterator_next grpc_auth_context_property_iterator grpc_auth_context_peer_identity diff --git a/grpc.gemspec b/grpc.gemspec index ace28715dc..475fc990ad 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -169,7 +169,6 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/sync_posix.h ) s.files += %w( include/grpc/impl/codegen/sync_win32.h ) s.files += %w( include/grpc/impl/codegen/time.h ) - s.files += %w( include/grpc/grpc_cronet.h ) s.files += %w( include/grpc/grpc_security.h ) s.files += %w( include/grpc/grpc_security_constants.h ) s.files += %w( include/grpc/census.h ) @@ -297,42 +296,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_config/subchannel_call_holder.h ) s.files += %w( src/core/ext/client_config/subchannel_index.h ) s.files += %w( src/core/ext/client_config/uri_parser.h ) - s.files += %w( include/grpc/byte_buffer.h ) - s.files += %w( include/grpc/grpc.h ) - s.files += %w( include/grpc/impl/codegen/alloc.h ) - s.files += %w( include/grpc/impl/codegen/atm.h ) - s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) - s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) - s.files += %w( include/grpc/impl/codegen/atm_win32.h ) - s.files += %w( include/grpc/impl/codegen/byte_buffer.h ) - s.files += %w( include/grpc/impl/codegen/compression_types.h ) - s.files += %w( include/grpc/impl/codegen/connectivity_state.h ) - s.files += %w( include/grpc/impl/codegen/grpc_types.h ) - s.files += %w( include/grpc/impl/codegen/log.h ) - s.files += %w( include/grpc/impl/codegen/port_platform.h ) - s.files += %w( include/grpc/impl/codegen/propagation_bits.h ) - s.files += %w( include/grpc/impl/codegen/slice.h ) - s.files += %w( include/grpc/impl/codegen/slice_buffer.h ) - s.files += %w( include/grpc/impl/codegen/status.h ) - s.files += %w( include/grpc/impl/codegen/sync.h ) - s.files += %w( include/grpc/impl/codegen/sync_generic.h ) - s.files += %w( include/grpc/impl/codegen/sync_posix.h ) - s.files += %w( include/grpc/impl/codegen/sync_win32.h ) - s.files += %w( include/grpc/impl/codegen/time.h ) - s.files += %w( include/grpc/status.h ) - s.files += %w( include/grpc/support/alloc.h ) - s.files += %w( include/grpc/support/atm.h ) - s.files += %w( include/grpc/support/host_port.h ) - s.files += %w( include/grpc/support/log.h ) - s.files += %w( include/grpc/support/port_platform.h ) - s.files += %w( include/grpc/support/slice.h ) - s.files += %w( include/grpc/support/slice_buffer.h ) - s.files += %w( include/grpc/support/string_util.h ) - s.files += %w( include/grpc/support/sync.h ) - s.files += %w( include/grpc/support/time.h ) - s.files += %w( include/grpc/support/useful.h ) - s.files += %w( src/core/lib/support/string.h ) - s.files += %w( third_party/objective_c/Cronet/cronet_c_for_grpc.h ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h ) s.files += %w( third_party/nanopb/pb.h ) @@ -491,9 +454,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_config/uri_parser.c ) s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) - s.files += %w( src/core/ext/transport/cronet/client/secure/cronet_channel_create.c ) - s.files += %w( src/core/ext/transport/cronet/transport/cronet_api_dummy.c ) - s.files += %w( src/core/ext/transport/cronet/transport/cronet_transport.c ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c ) s.files += %w( third_party/nanopb/pb_common.c ) diff --git a/include/grpc/grpc_cronet.h b/include/grpc/grpc_cronet.h deleted file mode 100644 index 295e0f55e8..0000000000 --- a/include/grpc/grpc_cronet.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_GRPC_CRONET_H -#define GRPC_GRPC_CRONET_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( - void *engine, const char *target, const grpc_channel_args *args, - void *reserved); - -#ifdef __cplusplus -} -#endif - -#endif /* GRPC_GRPC_CRONET_H */ diff --git a/package.xml b/package.xml index 152d5d6190..feb27175a9 100644 --- a/package.xml +++ b/package.xml @@ -176,7 +176,6 @@ - @@ -304,42 +303,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -498,9 +461,6 @@ - - - diff --git a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c deleted file mode 100644 index df1acddcc0..0000000000 --- a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include - -#include -#include - -#include -#include - -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/transport/transport_impl.h" - -// Cronet transport object -typedef struct cronet_transport { - grpc_transport base; // must be first element in this structure - void *engine; - char *host; -} cronet_transport; - -extern grpc_transport_vtable grpc_cronet_vtable; - -GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( - void *engine, const char *target, const grpc_channel_args *args, - void *reserved) { - cronet_transport *ct = gpr_malloc(sizeof(cronet_transport)); - ct->base.vtable = &grpc_cronet_vtable; - ct->engine = engine; - ct->host = gpr_malloc(strlen(target) + 1); - strcpy(ct->host, target); - gpr_log(GPR_DEBUG, - "grpc_create_cronet_transport: cronet_engine = %p, target=%s", engine, - ct->host); - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - return grpc_channel_create(&exec_ctx, target, args, - GRPC_CLIENT_DIRECT_CHANNEL, (grpc_transport *)ct); -} diff --git a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c deleted file mode 100644 index 687026c9fd..0000000000 --- a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/* This file has empty implementation of all the functions exposed by the cronet -library, so we can build it in all environments */ - -#include - -#include - -#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h" - -#ifdef GRPC_COMPILE_WITH_CRONET -/* link with the real CRONET library in the build system */ -#else -/* Dummy implementation of cronet API just to test for build-ability */ -cronet_bidirectional_stream* cronet_bidirectional_stream_create( - cronet_engine* engine, void* annotation, - cronet_bidirectional_stream_callback* callback) { - GPR_ASSERT(0); - return NULL; -} - -int cronet_bidirectional_stream_destroy(cronet_bidirectional_stream* stream) { - GPR_ASSERT(0); - return 0; -} - -int cronet_bidirectional_stream_start( - cronet_bidirectional_stream* stream, const char* url, int priority, - const char* method, const cronet_bidirectional_stream_header_array* headers, - bool end_of_stream) { - GPR_ASSERT(0); - return 0; -} - -int cronet_bidirectional_stream_read(cronet_bidirectional_stream* stream, - char* buffer, int capacity) { - GPR_ASSERT(0); - return 0; -} - -int cronet_bidirectional_stream_write(cronet_bidirectional_stream* stream, - const char* buffer, int count, - bool end_of_stream) { - GPR_ASSERT(0); - return 0; -} - -int cronet_bidirectional_stream_cancel(cronet_bidirectional_stream* stream) { - GPR_ASSERT(0); - return 0; -} - -#endif /* GRPC_COMPILE_WITH_CRONET */ diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c deleted file mode 100644 index 5bb085195c..0000000000 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ /dev/null @@ -1,640 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/transport/metadata_batch.h" -#include "src/core/lib/transport/transport_impl.h" -#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h" - -#define GRPC_HEADER_SIZE_IN_BYTES 5 - -// Global flag that gets set with GRPC_TRACE env variable -int grpc_cronet_trace = 1; - -// Cronet transport object -struct grpc_cronet_transport { - grpc_transport base; /* must be first element in this structure */ - cronet_engine *engine; - char *host; -}; - -typedef struct grpc_cronet_transport grpc_cronet_transport; - -enum send_state { - CRONET_SEND_IDLE = 0, - CRONET_REQ_STARTED, - CRONET_SEND_HEADER, - CRONET_WRITE, - CRONET_WRITE_COMPLETED, -}; - -enum recv_state { - CRONET_RECV_IDLE = 0, - CRONET_RECV_READ_LENGTH, - CRONET_RECV_READ_DATA, - CRONET_RECV_CLOSED, -}; - -static const char *recv_state_name[] = { - "CRONET_RECV_IDLE", "CRONET_RECV_READ_LENGTH", "CRONET_RECV_READ_DATA,", - "CRONET_RECV_CLOSED"}; - -// Enum that identifies calling function. -enum e_caller { - PERFORM_STREAM_OP, - ON_READ_COMPLETE, - ON_RESPONSE_HEADERS_RECEIVED, - ON_RESPONSE_TRAILERS_RECEIVED -}; - -enum callback_id { - CB_SEND_INITIAL_METADATA = 0, - CB_SEND_MESSAGE, - CB_SEND_TRAILING_METADATA, - CB_RECV_MESSAGE, - CB_RECV_INITIAL_METADATA, - CB_RECV_TRAILING_METADATA, - CB_NUM_CALLBACKS -}; - -struct stream_obj { - // we store received bytes here as they trickle in. - gpr_slice_buffer write_slice_buffer; - cronet_bidirectional_stream *cbs; - gpr_slice slice; - gpr_slice_buffer read_slice_buffer; - struct grpc_slice_buffer_stream sbs; - char *read_buffer; - int remaining_read_bytes; - int total_read_bytes; - - char *write_buffer; - size_t write_buffer_size; - - // Hold the URL - char *url; - - bool response_headers_received; - bool read_requested; - bool response_trailers_received; - bool read_closed; - - // Recv message stuff - grpc_byte_buffer **recv_message; - // Initial metadata stuff - grpc_metadata_batch *recv_initial_metadata; - // Trailing metadata stuff - grpc_metadata_batch *recv_trailing_metadata; - grpc_chttp2_incoming_metadata_buffer imb; - - // This mutex protects receive state machine execution - gpr_mu recv_mu; - // we can queue up up to 2 callbacks for each OP - grpc_closure *callback_list[CB_NUM_CALLBACKS][2]; - - // storage for header - cronet_bidirectional_stream_header *headers; - uint32_t num_headers; - cronet_bidirectional_stream_header_array header_array; - // state tracking - enum recv_state cronet_recv_state; - enum send_state cronet_send_state; -}; - -typedef struct stream_obj stream_obj; - -static void next_send_step(stream_obj *s); -static void next_recv_step(stream_obj *s, enum e_caller caller); - -static void set_pollset_do_nothing(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, grpc_pollset *pollset) {} - -static void enqueue_callbacks(grpc_closure *callback_list[]) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - if (callback_list[0]) { - grpc_exec_ctx_enqueue(&exec_ctx, callback_list[0], true, NULL); - callback_list[0] = NULL; - } - if (callback_list[1]) { - grpc_exec_ctx_enqueue(&exec_ctx, callback_list[1], true, NULL); - callback_list[1] = NULL; - } - grpc_exec_ctx_finish(&exec_ctx); -} - -static void on_canceled(cronet_bidirectional_stream *stream) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "on_canceled %p", stream); - } -} - -static void on_failed(cronet_bidirectional_stream *stream, int net_error) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "on_failed %p, error = %d", stream, net_error); - } -} - -static void on_succeeded(cronet_bidirectional_stream *stream) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "on_succeeded %p", stream); - } -} - -static void on_response_trailers_received( - cronet_bidirectional_stream *stream, - const cronet_bidirectional_stream_header_array *trailers) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: on_response_trailers_received"); - } - stream_obj *s = (stream_obj *)stream->annotation; - - memset(&s->imb, 0, sizeof(s->imb)); - grpc_chttp2_incoming_metadata_buffer_init(&s->imb); - unsigned int i = 0; - for (i = 0; i < trailers->count; i++) { - grpc_chttp2_incoming_metadata_buffer_add( - &s->imb, grpc_mdelem_from_metadata_strings( - grpc_mdstr_from_string(trailers->headers[i].key), - grpc_mdstr_from_string(trailers->headers[i].value))); - } - s->response_trailers_received = true; - next_recv_step(s, ON_RESPONSE_TRAILERS_RECEIVED); -} - -static void on_write_completed(cronet_bidirectional_stream *stream, - const char *data) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "W: on_write_completed"); - } - stream_obj *s = (stream_obj *)stream->annotation; - enqueue_callbacks(s->callback_list[CB_SEND_MESSAGE]); - s->cronet_send_state = CRONET_WRITE_COMPLETED; - next_send_step(s); -} - -static void process_recv_message(stream_obj *s, const uint8_t *recv_data) { - gpr_slice read_data_slice = gpr_slice_malloc((uint32_t)s->total_read_bytes); - uint8_t *dst_p = GPR_SLICE_START_PTR(read_data_slice); - memcpy(dst_p, recv_data, (size_t)s->total_read_bytes); - gpr_slice_buffer_add(&s->read_slice_buffer, read_data_slice); - grpc_slice_buffer_stream_init(&s->sbs, &s->read_slice_buffer, 0); - *s->recv_message = (grpc_byte_buffer *)&s->sbs; -} - -static int parse_grpc_header(const uint8_t *data) { - const uint8_t *p = data + 1; - int length = 0; - length |= ((uint8_t)*p++) << 24; - length |= ((uint8_t)*p++) << 16; - length |= ((uint8_t)*p++) << 8; - length |= ((uint8_t)*p++); - return length; -} - -static void on_read_completed(cronet_bidirectional_stream *stream, char *data, - int count) { - stream_obj *s = (stream_obj *)stream->annotation; - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: on_read_completed count=%d, total=%d, remaining=%d", - count, s->total_read_bytes, s->remaining_read_bytes); - } - if (count > 0) { - GPR_ASSERT(s->recv_message); - s->remaining_read_bytes -= count; - next_recv_step(s, ON_READ_COMPLETE); - } else { - s->read_closed = true; - next_recv_step(s, ON_READ_COMPLETE); - } -} - -static void on_response_headers_received( - cronet_bidirectional_stream *stream, - const cronet_bidirectional_stream_header_array *headers, - const char *negotiated_protocol) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: on_response_headers_received"); - } - stream_obj *s = (stream_obj *)stream->annotation; - enqueue_callbacks(s->callback_list[CB_RECV_INITIAL_METADATA]); - s->response_headers_received = true; - next_recv_step(s, ON_RESPONSE_HEADERS_RECEIVED); -} - -static void on_request_headers_sent(cronet_bidirectional_stream *stream) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "W: on_request_headers_sent"); - } - stream_obj *s = (stream_obj *)stream->annotation; - enqueue_callbacks(s->callback_list[CB_SEND_INITIAL_METADATA]); - s->cronet_send_state = CRONET_SEND_HEADER; - next_send_step(s); -} - -// Callback function pointers (invoked by cronet in response to events) -static cronet_bidirectional_stream_callback callbacks = { - on_request_headers_sent, - on_response_headers_received, - on_read_completed, - on_write_completed, - on_response_trailers_received, - on_succeeded, - on_failed, - on_canceled}; - -static void invoke_closing_callback(stream_obj *s) { - grpc_chttp2_incoming_metadata_buffer_publish(&s->imb, - s->recv_trailing_metadata); - if (s->callback_list[CB_RECV_TRAILING_METADATA]) { - enqueue_callbacks(s->callback_list[CB_RECV_TRAILING_METADATA]); - } -} - -static void set_recv_state(stream_obj *s, enum recv_state state) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "next_state = %s", recv_state_name[state]); - } - s->cronet_recv_state = state; -} - -// This is invoked from perform_stream_op, and all on_xxxx callbacks. -static void next_recv_step(stream_obj *s, enum e_caller caller) { - gpr_mu_lock(&s->recv_mu); - switch (s->cronet_recv_state) { - case CRONET_RECV_IDLE: - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_IDLE"); - } - if (caller == PERFORM_STREAM_OP || - caller == ON_RESPONSE_HEADERS_RECEIVED) { - if (s->read_closed && s->response_trailers_received) { - invoke_closing_callback(s); - set_recv_state(s, CRONET_RECV_CLOSED); - } else if (s->response_headers_received == true && - s->read_requested == true) { - set_recv_state(s, CRONET_RECV_READ_LENGTH); - s->total_read_bytes = s->remaining_read_bytes = - GRPC_HEADER_SIZE_IN_BYTES; - GPR_ASSERT(s->read_buffer); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()"); - } - cronet_bidirectional_stream_read(s->cbs, s->read_buffer, - s->remaining_read_bytes); - } - } - break; - case CRONET_RECV_READ_LENGTH: - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_LENGTH"); - } - if (caller == ON_READ_COMPLETE) { - if (s->read_closed) { - invoke_closing_callback(s); - enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]); - set_recv_state(s, CRONET_RECV_CLOSED); - } else { - GPR_ASSERT(s->remaining_read_bytes == 0); - set_recv_state(s, CRONET_RECV_READ_DATA); - s->total_read_bytes = s->remaining_read_bytes = - parse_grpc_header((const uint8_t *)s->read_buffer); - s->read_buffer = - gpr_realloc(s->read_buffer, (uint32_t)s->remaining_read_bytes); - GPR_ASSERT(s->read_buffer); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()"); - } - cronet_bidirectional_stream_read(s->cbs, (char *)s->read_buffer, - s->remaining_read_bytes); - } - } - break; - case CRONET_RECV_READ_DATA: - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_DATA"); - } - if (caller == ON_READ_COMPLETE) { - if (s->remaining_read_bytes > 0) { - int offset = s->total_read_bytes - s->remaining_read_bytes; - GPR_ASSERT(s->read_buffer); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()"); - } - cronet_bidirectional_stream_read( - s->cbs, (char *)s->read_buffer + offset, s->remaining_read_bytes); - } else { - gpr_slice_buffer_init(&s->read_slice_buffer); - uint8_t *p = (uint8_t *)s->read_buffer; - process_recv_message(s, p); - set_recv_state(s, CRONET_RECV_IDLE); - enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]); - } - } - break; - case CRONET_RECV_CLOSED: - break; - default: - GPR_ASSERT(0); // Should not reach here - break; - } - gpr_mu_unlock(&s->recv_mu); -} - -// This function takes the data from s->write_slice_buffer and assembles into -// a contiguous byte stream with 5 byte gRPC header prepended. -static void create_grpc_frame(stream_obj *s) { - gpr_slice slice = gpr_slice_buffer_take_first(&s->write_slice_buffer); - uint8_t *raw_data = GPR_SLICE_START_PTR(slice); - size_t length = GPR_SLICE_LENGTH(slice); - s->write_buffer_size = length + GRPC_HEADER_SIZE_IN_BYTES; - s->write_buffer = gpr_realloc(s->write_buffer, s->write_buffer_size); - uint8_t *p = (uint8_t *)s->write_buffer; - // Append 5 byte header - *p++ = 0; - *p++ = (uint8_t)(length >> 24); - *p++ = (uint8_t)(length >> 16); - *p++ = (uint8_t)(length >> 8); - *p++ = (uint8_t)(length); - // append actual data - memcpy(p, raw_data, length); -} - -static void do_write(stream_obj *s) { - gpr_slice_buffer *sb = &s->write_slice_buffer; - GPR_ASSERT(sb->count <= 1); - if (sb->count > 0) { - create_grpc_frame(s); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write"); - } - cronet_bidirectional_stream_write(s->cbs, s->write_buffer, - (int)s->write_buffer_size, false); - } -} - -// -static void next_send_step(stream_obj *s) { - switch (s->cronet_send_state) { - case CRONET_SEND_IDLE: - GPR_ASSERT( - s->cbs); // cronet_bidirectional_stream is not initialized yet. - s->cronet_send_state = CRONET_REQ_STARTED; - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_start to %s", s->url); - } - cronet_bidirectional_stream_start(s->cbs, s->url, 0, "POST", - &s->header_array, false); - // we no longer need the memory that was allocated earlier. - gpr_free(s->header_array.headers); - break; - case CRONET_SEND_HEADER: - do_write(s); - s->cronet_send_state = CRONET_WRITE; - break; - case CRONET_WRITE_COMPLETED: - do_write(s); - break; - default: - GPR_ASSERT(0); - break; - } -} - -static void convert_metadata_to_cronet_headers(grpc_linked_mdelem *head, - const char *host, - stream_obj *s) { - grpc_linked_mdelem *curr = head; - // Walk the linked list and get number of header fields - uint32_t num_headers_available = 0; - while (curr != NULL) { - curr = curr->next; - num_headers_available++; - } - // Allocate enough memory - s->headers = (cronet_bidirectional_stream_header *)gpr_malloc( - sizeof(cronet_bidirectional_stream_header) * num_headers_available); - - // Walk the linked list again, this time copying the header fields. - // s->num_headers - // can be less than num_headers_available, as some headers are not used for - // cronet - curr = head; - s->num_headers = 0; - while (s->num_headers < num_headers_available) { - grpc_mdelem *mdelem = curr->md; - curr = curr->next; - const char *key = grpc_mdstr_as_c_string(mdelem->key); - const char *value = grpc_mdstr_as_c_string(mdelem->value); - if (strcmp(key, ":scheme") == 0 || strcmp(key, ":method") == 0 || - strcmp(key, ":authority") == 0) { - // Cronet populates these fields on its own. - continue; - } - if (strcmp(key, ":path") == 0) { - // Create URL by appending :path value to the hostname - gpr_asprintf(&s->url, "https://%s%s", host, value); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "extracted URL = %s", s->url); - } - continue; - } - s->headers[s->num_headers].key = key; - s->headers[s->num_headers].value = value; - s->num_headers++; - if (curr == NULL) { - break; - } - } -} - -static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, grpc_transport_stream_op *op) { - grpc_cronet_transport *ct = (grpc_cronet_transport *)gt; - GPR_ASSERT(ct->engine); - stream_obj *s = (stream_obj *)gs; - if (op->recv_trailing_metadata) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, - "perform_stream_op - recv_trailing_metadata: on_complete=%p", - op->on_complete); - } - s->recv_trailing_metadata = op->recv_trailing_metadata; - GPR_ASSERT(!s->callback_list[CB_RECV_TRAILING_METADATA][0]); - s->callback_list[CB_RECV_TRAILING_METADATA][0] = op->on_complete; - } - if (op->recv_message) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "perform_stream_op - recv_message: on_complete=%p", - op->on_complete); - } - s->recv_message = (grpc_byte_buffer **)op->recv_message; - GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][0]); - GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][1]); - s->callback_list[CB_RECV_MESSAGE][0] = op->recv_message_ready; - s->callback_list[CB_RECV_MESSAGE][1] = op->on_complete; - s->read_requested = true; - next_recv_step(s, PERFORM_STREAM_OP); - } - if (op->recv_initial_metadata) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "perform_stream_op - recv_initial_metadata:=%p", - op->on_complete); - } - s->recv_initial_metadata = op->recv_initial_metadata; - GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][0]); - GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][1]); - s->callback_list[CB_RECV_INITIAL_METADATA][0] = - op->recv_initial_metadata_ready; - s->callback_list[CB_RECV_INITIAL_METADATA][1] = op->on_complete; - } - if (op->send_initial_metadata) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, - "perform_stream_op - send_initial_metadata: on_complete=%p", - op->on_complete); - } - s->num_headers = 0; - convert_metadata_to_cronet_headers(op->send_initial_metadata->list.head, - ct->host, s); - s->header_array.count = s->num_headers; - s->header_array.capacity = s->num_headers; - s->header_array.headers = s->headers; - GPR_ASSERT(!s->callback_list[CB_SEND_INITIAL_METADATA][0]); - s->callback_list[CB_SEND_INITIAL_METADATA][0] = op->on_complete; - } - if (op->send_message) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "perform_stream_op - send_message: on_complete=%p", - op->on_complete); - } - grpc_byte_stream_next(exec_ctx, op->send_message, &s->slice, - op->send_message->length, NULL); - // Check that compression flag is not ON. We don't support compression yet. - // TODO (makdharma): add compression support - GPR_ASSERT(op->send_message->flags == 0); - gpr_slice_buffer_add(&s->write_slice_buffer, s->slice); - if (s->cbs == NULL) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_create"); - } - s->cbs = cronet_bidirectional_stream_create(ct->engine, s, &callbacks); - GPR_ASSERT(s->cbs); - s->read_closed = false; - s->response_trailers_received = false; - s->response_headers_received = false; - s->cronet_send_state = CRONET_SEND_IDLE; - s->cronet_recv_state = CRONET_RECV_IDLE; - } - GPR_ASSERT(!s->callback_list[CB_SEND_MESSAGE][0]); - s->callback_list[CB_SEND_MESSAGE][0] = op->on_complete; - next_send_step(s); - } - if (op->send_trailing_metadata) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, - "perform_stream_op - send_trailing_metadata: on_complete=%p", - op->on_complete); - } - GPR_ASSERT(!s->callback_list[CB_SEND_TRAILING_METADATA][0]); - s->callback_list[CB_SEND_TRAILING_METADATA][0] = op->on_complete; - if (s->cbs) { - // Send an "empty" write to the far end to signal that we're done. - // This will induce the server to send down trailers. - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write"); - } - cronet_bidirectional_stream_write(s->cbs, "abc", 0, true); - } else { - // We never created a stream. This was probably an empty request. - invoke_closing_callback(s); - } - } -} - -static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, grpc_stream_refcount *refcount, - const void *server_data) { - stream_obj *s = (stream_obj *)gs; - memset(s->callback_list, 0, sizeof(s->callback_list)); - s->cbs = NULL; - gpr_mu_init(&s->recv_mu); - s->read_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES); - s->write_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES); - gpr_slice_buffer_init(&s->write_slice_buffer); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_transport - init_stream"); - } - return 0; -} - -static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, void *and_free_memory) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "Destroy stream"); - } - stream_obj *s = (stream_obj *)gs; - s->cbs = NULL; - gpr_free(s->read_buffer); - gpr_free(s->write_buffer); - gpr_free(s->url); - gpr_mu_destroy(&s->recv_mu); - if (and_free_memory) { - gpr_free(and_free_memory); - } -} - -static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { - grpc_cronet_transport *ct = (grpc_cronet_transport *)gt; - gpr_free(ct->host); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "Destroy transport"); - } -} - -const grpc_transport_vtable grpc_cronet_vtable = { - sizeof(stream_obj), "cronet_http", init_stream, - set_pollset_do_nothing, perform_stream_op, NULL, - destroy_stream, destroy_transport, NULL}; diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c index 09551472b5..f0a40dbb35 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.c +++ b/src/python/grpcio/grpc/_cython/imports.generated.c @@ -125,7 +125,6 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; -grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -396,7 +395,6 @@ void pygrpc_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); - grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h index 54c8aaad13..d5e810b7cf 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/python/grpcio/grpc/_cython/imports.generated.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -326,9 +325,6 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import -typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); -extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; -#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 5314329c2c..dab62530aa 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -222,9 +222,6 @@ CORE_SOURCE_FILES = [ 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', - 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', - 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', - 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index cebbe8c40f..bc43f9d36b 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -125,7 +125,6 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; -grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -392,7 +391,6 @@ void grpc_rb_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); - grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index d7ea6c574c..b67361ca25 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -326,9 +325,6 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import -typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); -extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; -#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index fd6ff2c26f..3eeb55d033 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include diff --git a/third_party/objective_c/Cronet/cronet_c_for_grpc.h b/third_party/objective_c/Cronet/cronet_c_for_grpc.h deleted file mode 100644 index 15a511aebd..0000000000 --- a/third_party/objective_c/Cronet/cronet_c_for_grpc.h +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ -#define COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* Cronet Engine API. */ - -/* Opaque object representing Cronet Engine. Created and configured outside - * of this API to facilitate sharing with other components */ -typedef struct cronet_engine { void* obj; } cronet_engine; - -void cronet_engine_add_quic_hint(cronet_engine* engine, - const char* host, - int port, - int alternate_port); - -/* Cronet Bidirectional Stream API */ - -/* Opaque object representing Cronet Bidirectional Stream. */ -typedef struct cronet_bidirectional_stream { - void* obj; - void* annotation; -} cronet_bidirectional_stream; - -/* A single request or response header element. */ -typedef struct cronet_bidirectional_stream_header { - const char* key; - const char* value; -} cronet_bidirectional_stream_header; - -/* Array of request or response headers or trailers. */ -typedef struct cronet_bidirectional_stream_header_array { - size_t count; - size_t capacity; - cronet_bidirectional_stream_header* headers; -} cronet_bidirectional_stream_header_array; - -/* Set of callbacks used to receive callbacks from bidirectional stream. */ -typedef struct cronet_bidirectional_stream_callback { - /* Invoked when request headers are sent. Indicates that stream has initiated - * the request. Consumer may call cronet_bidirectional_stream_write() to start - * writing data. - */ - void (*on_request_headers_sent)(cronet_bidirectional_stream* stream); - - /* Invoked when initial response headers are received. - * Consumer must call cronet_bidirectional_stream_read() to start reading. - * Consumer may call cronet_bidirectional_stream_write() to start writing or - * close the stream. Contents of |headers| is valid for duration of the call. - */ - void (*on_response_headers_received)( - cronet_bidirectional_stream* stream, - const cronet_bidirectional_stream_header_array* headers, - const char* negotiated_protocol); - - /* Invoked when data is read into the buffer passed to - * cronet_bidirectional_stream_read(). Only part of the buffer may be - * populated. To continue reading, call cronet_bidirectional_stream_read(). - * It may be invoked after on_response_trailers_received()}, if there was - * pending read data before trailers were received. - * - * If count is 0, it means the remote side has signaled that it will send no - * more data; future calls to cronet_bidirectional_stream_read() will result - * in the on_data_read() callback or on_succeded() callback if - * cronet_bidirectional_stream_write() was invoked with end_of_stream set to - * true. - */ - void (*on_read_completed)(cronet_bidirectional_stream* stream, - char* data, - int count); - - /** - * Invoked when all data passed to cronet_bidirectional_stream_write() is - * sent. - * To continue writing, call cronet_bidirectional_stream_write(). - */ - void (*on_write_completed)(cronet_bidirectional_stream* stream, - const char* data); - - /* Invoked when trailers are received before closing the stream. Only invoked - * when server sends trailers, which it may not. May be invoked while there is - * read data remaining in local buffer. Contents of |trailers| is valid for - * duration of the call. - */ - void (*on_response_trailers_received)( - cronet_bidirectional_stream* stream, - const cronet_bidirectional_stream_header_array* trailers); - - /** - * Invoked when there is no data to be read or written and the stream is - * closed successfully remotely and locally. Once invoked, no further callback - * methods will be invoked. - */ - void (*on_succeded)(cronet_bidirectional_stream* stream); - - /** - * Invoked if the stream failed for any reason after - * cronet_bidirectional_stream_start(). HTTP/2 error codes are - * mapped to chrome net error codes. Once invoked, no further callback methods - * will be invoked. - */ - void (*on_failed)(cronet_bidirectional_stream* stream, int net_error); - - /** - * Invoked if the stream was canceled via - * cronet_bidirectional_stream_cancel(). Once invoked, no further callback - * methods will be invoked. - */ - void (*on_canceled)(cronet_bidirectional_stream* stream); -} cronet_bidirectional_stream_callback; - -/* Create a new stream object that uses |engine| and |callback|. All stream - * tasks are performed asynchronously on the |engine| network thread. |callback| - * methods are invoked synchronously on the |engine| network thread, but must - * not run tasks on the current thread to prevent blocking networking operations - * and causing exceptions during shutdown. The |annotation| is stored in - * bidirectional stream for arbitrary use by application. - * - * Returned |cronet_bidirectional_stream*| is owned by the caller, and must be - * destroyed using |cronet_bidirectional_stream_destroy|. - * - * Both |calback| and |engine| must remain valid until stream is destroyed. - */ -cronet_bidirectional_stream* cronet_bidirectional_stream_create( - cronet_engine* engine, - void* annotation, - cronet_bidirectional_stream_callback* callback); - -/* TBD: The following methods return int. Should it be a custom type? */ - -/* Destroy stream object. Destroy could be called from any thread, including - * network thread, but is posted, so |stream| is valid until calling task is - * complete. - */ -int cronet_bidirectional_stream_destroy(cronet_bidirectional_stream* stream); - -/* Start the stream by sending request to |url| using |method| and |headers|. If - * |end_of_stream| is true, then no data is expected to be written. - */ -int cronet_bidirectional_stream_start( - cronet_bidirectional_stream* stream, - const char* url, - int priority, - const char* method, - const cronet_bidirectional_stream_header_array* headers, - bool end_of_stream); - -/* Read response data into |buffer| of |capacity| length. Must only be called at - * most once in response to each invocation of the - * on_response_headers_received() and on_read_completed() methods of the - * cronet_bidirectional_stream_callback. - * Each call will result in an invocation of one of the callback's - * on_read_completed method if data is read, its on_succeeded() method if - * the stream is closed, or its on_failed() method if there's an error. - */ -int cronet_bidirectional_stream_read(cronet_bidirectional_stream* stream, - char* buffer, - int capacity); - -/* Read response data into |buffer| of |capacity| length. Must only be called at - * most once in response to each invocation of the - * on_response_headers_received() and on_read_completed() methods of the - * cronet_bidirectional_stream_callback. - * Each call will result in an invocation of one of the callback's - * on_read_completed method if data is read, its on_succeeded() method if - * the stream is closed, or its on_failed() method if there's an error. - */ -int cronet_bidirectional_stream_write(cronet_bidirectional_stream* stream, - const char* buffer, - int count, - bool end_of_stream); - -/* Cancels the stream. Can be called at any time after - * cronet_bidirectional_stream_start(). The on_canceled() method of - * cronet_bidirectional_stream_callback will be invoked when cancelation - * is complete and no further callback methods will be invoked. If the - * stream has completed or has not started, calling - * cronet_bidirectional_stream_cancel() has no effect and on_canceled() will not - * be invoked. At most one callback method may be invoked after - * cronet_bidirectional_stream_cancel() has completed. - */ -int cronet_bidirectional_stream_cancel(cronet_bidirectional_stream* stream); - -/* Returns true if the |stream| was successfully started and is now done - * (succeeded, canceled, or failed). - * Returns false if the |stream| stream is not yet started or is in progress. - */ -bool cronet_bidirectional_stream_is_done(cronet_bidirectional_stream* stream); - -#ifdef __cplusplus -} -#endif - -#endif // COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index aabca410da..eed84252cc 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -786,7 +786,6 @@ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ -include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 3ffc6174ed..1fcc1fa140 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -786,7 +786,6 @@ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ -include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -914,42 +913,6 @@ src/core/ext/client_config/subchannel.h \ src/core/ext/client_config/subchannel_call_holder.h \ src/core/ext/client_config/subchannel_index.h \ src/core/ext/client_config/uri_parser.h \ -include/grpc/byte_buffer.h \ -include/grpc/grpc.h \ -include/grpc/impl/codegen/alloc.h \ -include/grpc/impl/codegen/atm.h \ -include/grpc/impl/codegen/atm_gcc_atomic.h \ -include/grpc/impl/codegen/atm_gcc_sync.h \ -include/grpc/impl/codegen/atm_win32.h \ -include/grpc/impl/codegen/byte_buffer.h \ -include/grpc/impl/codegen/compression_types.h \ -include/grpc/impl/codegen/connectivity_state.h \ -include/grpc/impl/codegen/grpc_types.h \ -include/grpc/impl/codegen/log.h \ -include/grpc/impl/codegen/port_platform.h \ -include/grpc/impl/codegen/propagation_bits.h \ -include/grpc/impl/codegen/slice.h \ -include/grpc/impl/codegen/slice_buffer.h \ -include/grpc/impl/codegen/status.h \ -include/grpc/impl/codegen/sync.h \ -include/grpc/impl/codegen/sync_generic.h \ -include/grpc/impl/codegen/sync_posix.h \ -include/grpc/impl/codegen/sync_win32.h \ -include/grpc/impl/codegen/time.h \ -include/grpc/status.h \ -include/grpc/support/alloc.h \ -include/grpc/support/atm.h \ -include/grpc/support/host_port.h \ -include/grpc/support/log.h \ -include/grpc/support/port_platform.h \ -include/grpc/support/slice.h \ -include/grpc/support/slice_buffer.h \ -include/grpc/support/string_util.h \ -include/grpc/support/sync.h \ -include/grpc/support/time.h \ -include/grpc/support/useful.h \ -src/core/lib/support/string.h \ -third_party/objective_c/Cronet/cronet_c_for_grpc.h \ src/core/ext/lb_policy/grpclb/load_balancer_api.h \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h \ third_party/nanopb/pb.h \ @@ -1108,9 +1071,6 @@ src/core/ext/client_config/subchannel_index.c \ src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ -src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ -src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ -src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 8c67d2f844..3b3a49a5b2 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -4140,8 +4140,7 @@ "grpc_transport_chttp2_client_insecure", "grpc_transport_chttp2_client_secure", "grpc_transport_chttp2_server_insecure", - "grpc_transport_chttp2_server_secure", - "grpc_transport_cronet_client_secure" + "grpc_transport_chttp2_server_secure" ], "headers": [], "language": "c", @@ -6015,7 +6014,6 @@ "tsi" ], "headers": [ - "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "src/core/lib/security/auth_filters.h", @@ -6031,7 +6029,6 @@ "language": "c", "name": "grpc_secure", "src": [ - "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "src/core/lib/http/httpcli_security_connector.c", @@ -6267,121 +6264,6 @@ "third_party": false, "type": "filegroup" }, - { - "deps": [], - "headers": [ - "include/grpc/byte_buffer.h", - "include/grpc/grpc.h", - "include/grpc/impl/codegen/alloc.h", - "include/grpc/impl/codegen/atm.h", - "include/grpc/impl/codegen/atm_gcc_atomic.h", - "include/grpc/impl/codegen/atm_gcc_sync.h", - "include/grpc/impl/codegen/atm_win32.h", - "include/grpc/impl/codegen/byte_buffer.h", - "include/grpc/impl/codegen/compression_types.h", - "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/grpc_types.h", - "include/grpc/impl/codegen/log.h", - "include/grpc/impl/codegen/port_platform.h", - "include/grpc/impl/codegen/propagation_bits.h", - "include/grpc/impl/codegen/slice.h", - "include/grpc/impl/codegen/slice_buffer.h", - "include/grpc/impl/codegen/status.h", - "include/grpc/impl/codegen/sync.h", - "include/grpc/impl/codegen/sync_generic.h", - "include/grpc/impl/codegen/sync_posix.h", - "include/grpc/impl/codegen/sync_win32.h", - "include/grpc/impl/codegen/time.h", - "include/grpc/status.h", - "include/grpc/support/alloc.h", - "include/grpc/support/atm.h", - "include/grpc/support/host_port.h", - "include/grpc/support/log.h", - "include/grpc/support/port_platform.h", - "include/grpc/support/slice.h", - "include/grpc/support/slice_buffer.h", - "include/grpc/support/string_util.h", - "include/grpc/support/sync.h", - "include/grpc/support/time.h", - "include/grpc/support/useful.h", - "src/core/ext/transport/chttp2/transport/incoming_metadata.h", - "src/core/lib/channel/channel_stack.h", - "src/core/lib/channel/context.h", - "src/core/lib/debug/trace.h", - "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/exec_ctx.h", - "src/core/lib/iomgr/pollset.h", - "src/core/lib/iomgr/pollset_set.h", - "src/core/lib/support/string.h", - "src/core/lib/surface/channel.h", - "src/core/lib/surface/channel_stack_type.h", - "src/core/lib/transport/byte_stream.h", - "src/core/lib/transport/metadata.h", - "src/core/lib/transport/metadata_batch.h", - "src/core/lib/transport/transport.h", - "src/core/lib/transport/transport_impl.h", - "third_party/objective_c/Cronet/cronet_c_for_grpc.h" - ], - "language": "c", - "name": "grpc_transport_cronet_client_secure", - "src": [ - "include/grpc/byte_buffer.h", - "include/grpc/grpc.h", - "include/grpc/impl/codegen/alloc.h", - "include/grpc/impl/codegen/atm.h", - "include/grpc/impl/codegen/atm_gcc_atomic.h", - "include/grpc/impl/codegen/atm_gcc_sync.h", - "include/grpc/impl/codegen/atm_win32.h", - "include/grpc/impl/codegen/byte_buffer.h", - "include/grpc/impl/codegen/compression_types.h", - "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/grpc_types.h", - "include/grpc/impl/codegen/log.h", - "include/grpc/impl/codegen/port_platform.h", - "include/grpc/impl/codegen/propagation_bits.h", - "include/grpc/impl/codegen/slice.h", - "include/grpc/impl/codegen/slice_buffer.h", - "include/grpc/impl/codegen/status.h", - "include/grpc/impl/codegen/sync.h", - "include/grpc/impl/codegen/sync_generic.h", - "include/grpc/impl/codegen/sync_posix.h", - "include/grpc/impl/codegen/sync_win32.h", - "include/grpc/impl/codegen/time.h", - "include/grpc/status.h", - "include/grpc/support/alloc.h", - "include/grpc/support/atm.h", - "include/grpc/support/host_port.h", - "include/grpc/support/log.h", - "include/grpc/support/port_platform.h", - "include/grpc/support/slice.h", - "include/grpc/support/slice_buffer.h", - "include/grpc/support/string_util.h", - "include/grpc/support/sync.h", - "include/grpc/support/time.h", - "include/grpc/support/useful.h", - "src/core/ext/transport/chttp2/transport/incoming_metadata.h", - "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", - "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", - "src/core/ext/transport/cronet/transport/cronet_transport.c", - "src/core/lib/channel/channel_stack.h", - "src/core/lib/channel/context.h", - "src/core/lib/debug/trace.h", - "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/exec_ctx.h", - "src/core/lib/iomgr/pollset.h", - "src/core/lib/iomgr/pollset_set.h", - "src/core/lib/support/string.h", - "src/core/lib/surface/channel.h", - "src/core/lib/surface/channel_stack_type.h", - "src/core/lib/transport/byte_stream.h", - "src/core/lib/transport/metadata.h", - "src/core/lib/transport/metadata_batch.h", - "src/core/lib/transport/transport.h", - "src/core/lib/transport/transport_impl.h" - ], - "third_party": false, - "type": "filegroup" - }, { "deps": [], "headers": [ diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 7f0e5a8339..03f4eaa5be 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -293,7 +293,6 @@ - @@ -423,42 +422,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -765,12 +728,6 @@ - - - - - - diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 6d1d69a913..4617e3de0d 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -439,15 +439,6 @@ src\core\ext\transport\chttp2\client\insecure - - src\core\ext\transport\cronet\client\secure - - - src\core\ext\transport\cronet\transport - - - src\core\ext\transport\cronet\transport - src\core\ext\lb_policy\grpclb @@ -585,9 +576,6 @@ include\grpc\impl\codegen - - include\grpc - include\grpc @@ -971,114 +959,6 @@ src\core\ext\client_config - - include\grpc - - - include\grpc - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - src\core\lib\support - - - third_party\objective_c\Cronet - src\core\ext\lb_policy\grpclb @@ -1130,9 +1010,6 @@ {def748f5-ed2a-a9bb-40d9-c31d00f0e13b} - - {31de82ea-dc6c-73fb-a640-979b8a7b240c} - {d538af37-07b2-062b-fa2a-d9f882cb2737} @@ -1214,18 +1091,6 @@ {6f34254e-e69f-c9b4-156d-5024bade5408} - - {1e9c85e9-5522-7ef8-0017-7e19990a6194} - - - {d0530883-75d9-b5f7-d594-26735a70ac7b} - - - {4fa6fe90-b7a8-5c8f-d629-db1e68d89eed} - - - {31518af8-5860-6d0d-ff78-4059fce29ec2} - {5b2ded3f-84a5-f6b4-2060-286c7d1dc945} @@ -1250,9 +1115,6 @@ {c4661d64-349f-01c1-1ba8-0602f9047595} - - {27f30339-d694-40f5-db07-4b89b9aeea73} - {a21971fb-304f-da08-b1b2-7bd8df8ac373} @@ -1271,12 +1133,6 @@ {93d6596d-330c-1d27-6f84-3c840e57869e} - - {3a56a516-857e-d2aa-95cc-11685baf4e8c} - - - {a165c6e3-0776-6f40-7351-d7865668e220} - -- cgit v1.2.3 From 0545d7fa6900b66dfd37de7a33fe5fdc655a378d Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Mon, 9 May 2016 19:28:17 +0200 Subject: Revert "Merge pull request #6214 from makdharma/master" This reverts commit 48d833a9d8280216040ef731341502d7d0f157e4, reversing changes made to 66e9d8e8a7717d7ccece629df4454fc546e19daa. --- BUILD | 80 --- Makefile | 7 - binding.gyp | 3 - build.yaml | 59 -- config.m4 | 5 - gRPC.podspec | 76 --- grpc.def | 1 - grpc.gemspec | 40 -- include/grpc/grpc_cronet.h | 51 -- package.xml | 40 -- .../cronet/client/secure/cronet_channel_create.c | 69 --- .../transport/cronet/transport/cronet_api_dummy.c | 85 --- .../transport/cronet/transport/cronet_transport.c | 640 --------------------- src/python/grpcio/grpc/_cython/imports.generated.c | 2 - src/python/grpcio/grpc/_cython/imports.generated.h | 4 - src/python/grpcio/grpc_core_dependencies.py | 3 - src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 - src/ruby/ext/grpc/rb_grpc_imports.generated.h | 4 - test/core/surface/public_headers_must_be_c89.c | 1 - third_party/objective_c/Cronet/cronet_c_for_grpc.h | 202 ------- tools/doxygen/Doxyfile.core | 1 - tools/doxygen/Doxyfile.core.internal | 40 -- tools/run_tests/sources_and_headers.json | 120 +--- vsprojects/vcxproj/grpc/grpc.vcxproj | 43 -- vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 144 ----- 25 files changed, 1 insertion(+), 1721 deletions(-) delete mode 100644 include/grpc/grpc_cronet.h delete mode 100644 src/core/ext/transport/cronet/client/secure/cronet_channel_create.c delete mode 100644 src/core/ext/transport/cronet/transport/cronet_api_dummy.c delete mode 100644 src/core/ext/transport/cronet/transport/cronet_transport.c delete mode 100644 third_party/objective_c/Cronet/cronet_c_for_grpc.h (limited to 'src/python/grpcio') diff --git a/BUILD b/BUILD index fae3596eec..1da1650438 100644 --- a/BUILD +++ b/BUILD @@ -285,42 +285,6 @@ cc_library( "src/core/ext/client_config/subchannel_call_holder.h", "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", - "include/grpc/byte_buffer.h", - "include/grpc/grpc.h", - "include/grpc/impl/codegen/alloc.h", - "include/grpc/impl/codegen/atm.h", - "include/grpc/impl/codegen/atm_gcc_atomic.h", - "include/grpc/impl/codegen/atm_gcc_sync.h", - "include/grpc/impl/codegen/atm_win32.h", - "include/grpc/impl/codegen/byte_buffer.h", - "include/grpc/impl/codegen/compression_types.h", - "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/grpc_types.h", - "include/grpc/impl/codegen/log.h", - "include/grpc/impl/codegen/port_platform.h", - "include/grpc/impl/codegen/propagation_bits.h", - "include/grpc/impl/codegen/slice.h", - "include/grpc/impl/codegen/slice_buffer.h", - "include/grpc/impl/codegen/status.h", - "include/grpc/impl/codegen/sync.h", - "include/grpc/impl/codegen/sync_generic.h", - "include/grpc/impl/codegen/sync_posix.h", - "include/grpc/impl/codegen/sync_win32.h", - "include/grpc/impl/codegen/time.h", - "include/grpc/status.h", - "include/grpc/support/alloc.h", - "include/grpc/support/atm.h", - "include/grpc/support/host_port.h", - "include/grpc/support/log.h", - "include/grpc/support/port_platform.h", - "include/grpc/support/slice.h", - "include/grpc/support/slice_buffer.h", - "include/grpc/support/string_util.h", - "include/grpc/support/sync.h", - "include/grpc/support/time.h", - "include/grpc/support/useful.h", - "src/core/lib/support/string.h", - "third_party/objective_c/Cronet/cronet_c_for_grpc.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", "src/core/ext/census/aggregation.h", @@ -475,9 +439,6 @@ cc_library( "src/core/ext/client_config/uri_parser.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", - "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", - "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", - "src/core/ext/transport/cronet/transport/cronet_transport.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", @@ -522,7 +483,6 @@ cc_library( "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_win32.h", "include/grpc/impl/codegen/time.h", - "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "include/grpc/census.h", @@ -1500,9 +1460,6 @@ objc_library( "src/core/ext/client_config/uri_parser.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", - "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", - "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", - "src/core/ext/transport/cronet/transport/cronet_transport.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", @@ -1547,7 +1504,6 @@ objc_library( "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_win32.h", "include/grpc/impl/codegen/time.h", - "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "include/grpc/census.h", @@ -1675,42 +1631,6 @@ objc_library( "src/core/ext/client_config/subchannel_call_holder.h", "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", - "include/grpc/byte_buffer.h", - "include/grpc/grpc.h", - "include/grpc/impl/codegen/alloc.h", - "include/grpc/impl/codegen/atm.h", - "include/grpc/impl/codegen/atm_gcc_atomic.h", - "include/grpc/impl/codegen/atm_gcc_sync.h", - "include/grpc/impl/codegen/atm_win32.h", - "include/grpc/impl/codegen/byte_buffer.h", - "include/grpc/impl/codegen/compression_types.h", - "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/grpc_types.h", - "include/grpc/impl/codegen/log.h", - "include/grpc/impl/codegen/port_platform.h", - "include/grpc/impl/codegen/propagation_bits.h", - "include/grpc/impl/codegen/slice.h", - "include/grpc/impl/codegen/slice_buffer.h", - "include/grpc/impl/codegen/status.h", - "include/grpc/impl/codegen/sync.h", - "include/grpc/impl/codegen/sync_generic.h", - "include/grpc/impl/codegen/sync_posix.h", - "include/grpc/impl/codegen/sync_win32.h", - "include/grpc/impl/codegen/time.h", - "include/grpc/status.h", - "include/grpc/support/alloc.h", - "include/grpc/support/atm.h", - "include/grpc/support/host_port.h", - "include/grpc/support/log.h", - "include/grpc/support/port_platform.h", - "include/grpc/support/slice.h", - "include/grpc/support/slice_buffer.h", - "include/grpc/support/string_util.h", - "include/grpc/support/sync.h", - "include/grpc/support/time.h", - "include/grpc/support/useful.h", - "src/core/lib/support/string.h", - "third_party/objective_c/Cronet/cronet_c_for_grpc.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h", "src/core/ext/census/aggregation.h", diff --git a/Makefile b/Makefile index 635df30c20..45003ad8b5 100644 --- a/Makefile +++ b/Makefile @@ -2623,9 +2623,6 @@ LIBGRPC_SRC = \ src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ - src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ - src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -2673,7 +2670,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ - include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -14321,9 +14317,6 @@ ifneq ($(OPENSSL_DEP),) # otherwise parallel compilation will fail if a source is compiled first. src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP) -src/core/ext/transport/cronet/client/secure/cronet_channel_create.c: $(OPENSSL_DEP) -src/core/ext/transport/cronet/transport/cronet_api_dummy.c: $(OPENSSL_DEP) -src/core/ext/transport/cronet/transport/cronet_transport.c: $(OPENSSL_DEP) src/core/lib/http/httpcli_security_connector.c: $(OPENSSL_DEP) src/core/lib/security/b64.c: $(OPENSSL_DEP) src/core/lib/security/client_auth_filter.c: $(OPENSSL_DEP) diff --git a/binding.gyp b/binding.gyp index 12a745ffb0..4314ab7243 100644 --- a/binding.gyp +++ b/binding.gyp @@ -709,9 +709,6 @@ 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', - 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', - 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', - 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/build.yaml b/build.yaml index 7a74e73c72..a21dc688ad 100644 --- a/build.yaml +++ b/build.yaml @@ -400,7 +400,6 @@ filegroups: - grpc_client_config - name: grpc_secure public_headers: - - include/grpc/grpc_cronet.h - include/grpc/grpc_security.h - include/grpc/grpc_security_constants.h headers: @@ -548,63 +547,6 @@ filegroups: - grpc_transport_chttp2 - grpc_base - grpc_secure -- name: grpc_transport_cronet_client_secure - headers: - - include/grpc/byte_buffer.h - - include/grpc/grpc.h - - include/grpc/impl/codegen/alloc.h - - include/grpc/impl/codegen/atm.h - - include/grpc/impl/codegen/atm_gcc_atomic.h - - include/grpc/impl/codegen/atm_gcc_sync.h - - include/grpc/impl/codegen/atm_win32.h - - include/grpc/impl/codegen/byte_buffer.h - - include/grpc/impl/codegen/compression_types.h - - include/grpc/impl/codegen/connectivity_state.h - - include/grpc/impl/codegen/grpc_types.h - - include/grpc/impl/codegen/log.h - - include/grpc/impl/codegen/port_platform.h - - include/grpc/impl/codegen/propagation_bits.h - - include/grpc/impl/codegen/slice.h - - include/grpc/impl/codegen/slice_buffer.h - - include/grpc/impl/codegen/status.h - - include/grpc/impl/codegen/sync.h - - include/grpc/impl/codegen/sync_generic.h - - include/grpc/impl/codegen/sync_posix.h - - include/grpc/impl/codegen/sync_win32.h - - include/grpc/impl/codegen/time.h - - include/grpc/status.h - - include/grpc/support/alloc.h - - include/grpc/support/atm.h - - include/grpc/support/host_port.h - - include/grpc/support/log.h - - include/grpc/support/port_platform.h - - include/grpc/support/slice.h - - include/grpc/support/slice_buffer.h - - include/grpc/support/string_util.h - - include/grpc/support/sync.h - - include/grpc/support/time.h - - include/grpc/support/useful.h - - src/core/ext/transport/chttp2/transport/incoming_metadata.h - - src/core/lib/channel/channel_stack.h - - src/core/lib/channel/context.h - - src/core/lib/debug/trace.h - - src/core/lib/iomgr/closure.h - - src/core/lib/iomgr/exec_ctx.h - - src/core/lib/iomgr/pollset.h - - src/core/lib/iomgr/pollset_set.h - - src/core/lib/support/string.h - - src/core/lib/surface/channel.h - - src/core/lib/surface/channel_stack_type.h - - src/core/lib/transport/byte_stream.h - - src/core/lib/transport/metadata.h - - src/core/lib/transport/metadata_batch.h - - src/core/lib/transport/transport.h - - src/core/lib/transport/transport_impl.h - - third_party/objective_c/Cronet/cronet_c_for_grpc.h - src: - - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c - - src/core/ext/transport/cronet/transport/cronet_api_dummy.c - - src/core/ext/transport/cronet/transport/cronet_transport.c - name: nanopb headers: - third_party/nanopb/pb.h @@ -792,7 +734,6 @@ libs: - grpc_transport_chttp2_client_secure - grpc_transport_chttp2_server_insecure - grpc_transport_chttp2_client_insecure - - grpc_transport_cronet_client_secure - grpc_lb_policy_grpclb - grpc_lb_policy_pick_first - grpc_lb_policy_round_robin diff --git a/config.m4 b/config.m4 index 5259e679ba..74f9ad242a 100644 --- a/config.m4 +++ b/config.m4 @@ -228,9 +228,6 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ - src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ - src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -569,8 +566,6 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/insecure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/secure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport) - PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/cronet/client/secure) - PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/cronet/transport) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/channel) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug) diff --git a/gRPC.podspec b/gRPC.podspec index 018306ca64..569f89bf7c 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -287,42 +287,6 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_call_holder.h', 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', - 'include/grpc/byte_buffer.h', - 'include/grpc/grpc.h', - 'include/grpc/impl/codegen/alloc.h', - 'include/grpc/impl/codegen/atm.h', - 'include/grpc/impl/codegen/atm_gcc_atomic.h', - 'include/grpc/impl/codegen/atm_gcc_sync.h', - 'include/grpc/impl/codegen/atm_win32.h', - 'include/grpc/impl/codegen/byte_buffer.h', - 'include/grpc/impl/codegen/compression_types.h', - 'include/grpc/impl/codegen/connectivity_state.h', - 'include/grpc/impl/codegen/grpc_types.h', - 'include/grpc/impl/codegen/log.h', - 'include/grpc/impl/codegen/port_platform.h', - 'include/grpc/impl/codegen/propagation_bits.h', - 'include/grpc/impl/codegen/slice.h', - 'include/grpc/impl/codegen/slice_buffer.h', - 'include/grpc/impl/codegen/status.h', - 'include/grpc/impl/codegen/sync.h', - 'include/grpc/impl/codegen/sync_generic.h', - 'include/grpc/impl/codegen/sync_posix.h', - 'include/grpc/impl/codegen/sync_win32.h', - 'include/grpc/impl/codegen/time.h', - 'include/grpc/status.h', - 'include/grpc/support/alloc.h', - 'include/grpc/support/atm.h', - 'include/grpc/support/host_port.h', - 'include/grpc/support/log.h', - 'include/grpc/support/port_platform.h', - 'include/grpc/support/slice.h', - 'include/grpc/support/slice_buffer.h', - 'include/grpc/support/string_util.h', - 'include/grpc/support/sync.h', - 'include/grpc/support/time.h', - 'include/grpc/support/useful.h', - 'src/core/lib/support/string.h', - 'third_party/objective_c/Cronet/cronet_c_for_grpc.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', 'third_party/nanopb/pb.h', @@ -361,7 +325,6 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/sync_posix.h', 'include/grpc/impl/codegen/sync_win32.h', 'include/grpc/impl/codegen/time.h', - 'include/grpc/grpc_cronet.h', 'include/grpc/grpc_security.h', 'include/grpc/grpc_security_constants.h', 'include/grpc/census.h', @@ -511,9 +474,6 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', - 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', - 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', - 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', @@ -670,42 +630,6 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_call_holder.h', 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', - 'include/grpc/byte_buffer.h', - 'include/grpc/grpc.h', - 'include/grpc/impl/codegen/alloc.h', - 'include/grpc/impl/codegen/atm.h', - 'include/grpc/impl/codegen/atm_gcc_atomic.h', - 'include/grpc/impl/codegen/atm_gcc_sync.h', - 'include/grpc/impl/codegen/atm_win32.h', - 'include/grpc/impl/codegen/byte_buffer.h', - 'include/grpc/impl/codegen/compression_types.h', - 'include/grpc/impl/codegen/connectivity_state.h', - 'include/grpc/impl/codegen/grpc_types.h', - 'include/grpc/impl/codegen/log.h', - 'include/grpc/impl/codegen/port_platform.h', - 'include/grpc/impl/codegen/propagation_bits.h', - 'include/grpc/impl/codegen/slice.h', - 'include/grpc/impl/codegen/slice_buffer.h', - 'include/grpc/impl/codegen/status.h', - 'include/grpc/impl/codegen/sync.h', - 'include/grpc/impl/codegen/sync_generic.h', - 'include/grpc/impl/codegen/sync_posix.h', - 'include/grpc/impl/codegen/sync_win32.h', - 'include/grpc/impl/codegen/time.h', - 'include/grpc/status.h', - 'include/grpc/support/alloc.h', - 'include/grpc/support/atm.h', - 'include/grpc/support/host_port.h', - 'include/grpc/support/log.h', - 'include/grpc/support/port_platform.h', - 'include/grpc/support/slice.h', - 'include/grpc/support/slice_buffer.h', - 'include/grpc/support/string_util.h', - 'include/grpc/support/sync.h', - 'include/grpc/support/time.h', - 'include/grpc/support/useful.h', - 'src/core/lib/support/string.h', - 'third_party/objective_c/Cronet/cronet_c_for_grpc.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h', 'third_party/nanopb/pb.h', diff --git a/grpc.def b/grpc.def index 09a94a6cd0..61948ed1b8 100644 --- a/grpc.def +++ b/grpc.def @@ -87,7 +87,6 @@ EXPORTS grpc_header_nonbin_value_is_legal grpc_is_binary_header grpc_call_error_to_string - grpc_cronet_secure_channel_create grpc_auth_property_iterator_next grpc_auth_context_property_iterator grpc_auth_context_peer_identity diff --git a/grpc.gemspec b/grpc.gemspec index ace28715dc..475fc990ad 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -169,7 +169,6 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/sync_posix.h ) s.files += %w( include/grpc/impl/codegen/sync_win32.h ) s.files += %w( include/grpc/impl/codegen/time.h ) - s.files += %w( include/grpc/grpc_cronet.h ) s.files += %w( include/grpc/grpc_security.h ) s.files += %w( include/grpc/grpc_security_constants.h ) s.files += %w( include/grpc/census.h ) @@ -297,42 +296,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_config/subchannel_call_holder.h ) s.files += %w( src/core/ext/client_config/subchannel_index.h ) s.files += %w( src/core/ext/client_config/uri_parser.h ) - s.files += %w( include/grpc/byte_buffer.h ) - s.files += %w( include/grpc/grpc.h ) - s.files += %w( include/grpc/impl/codegen/alloc.h ) - s.files += %w( include/grpc/impl/codegen/atm.h ) - s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) - s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) - s.files += %w( include/grpc/impl/codegen/atm_win32.h ) - s.files += %w( include/grpc/impl/codegen/byte_buffer.h ) - s.files += %w( include/grpc/impl/codegen/compression_types.h ) - s.files += %w( include/grpc/impl/codegen/connectivity_state.h ) - s.files += %w( include/grpc/impl/codegen/grpc_types.h ) - s.files += %w( include/grpc/impl/codegen/log.h ) - s.files += %w( include/grpc/impl/codegen/port_platform.h ) - s.files += %w( include/grpc/impl/codegen/propagation_bits.h ) - s.files += %w( include/grpc/impl/codegen/slice.h ) - s.files += %w( include/grpc/impl/codegen/slice_buffer.h ) - s.files += %w( include/grpc/impl/codegen/status.h ) - s.files += %w( include/grpc/impl/codegen/sync.h ) - s.files += %w( include/grpc/impl/codegen/sync_generic.h ) - s.files += %w( include/grpc/impl/codegen/sync_posix.h ) - s.files += %w( include/grpc/impl/codegen/sync_win32.h ) - s.files += %w( include/grpc/impl/codegen/time.h ) - s.files += %w( include/grpc/status.h ) - s.files += %w( include/grpc/support/alloc.h ) - s.files += %w( include/grpc/support/atm.h ) - s.files += %w( include/grpc/support/host_port.h ) - s.files += %w( include/grpc/support/log.h ) - s.files += %w( include/grpc/support/port_platform.h ) - s.files += %w( include/grpc/support/slice.h ) - s.files += %w( include/grpc/support/slice_buffer.h ) - s.files += %w( include/grpc/support/string_util.h ) - s.files += %w( include/grpc/support/sync.h ) - s.files += %w( include/grpc/support/time.h ) - s.files += %w( include/grpc/support/useful.h ) - s.files += %w( src/core/lib/support/string.h ) - s.files += %w( third_party/objective_c/Cronet/cronet_c_for_grpc.h ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h ) s.files += %w( third_party/nanopb/pb.h ) @@ -491,9 +454,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_config/uri_parser.c ) s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) - s.files += %w( src/core/ext/transport/cronet/client/secure/cronet_channel_create.c ) - s.files += %w( src/core/ext/transport/cronet/transport/cronet_api_dummy.c ) - s.files += %w( src/core/ext/transport/cronet/transport/cronet_transport.c ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c ) s.files += %w( third_party/nanopb/pb_common.c ) diff --git a/include/grpc/grpc_cronet.h b/include/grpc/grpc_cronet.h deleted file mode 100644 index 295e0f55e8..0000000000 --- a/include/grpc/grpc_cronet.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_GRPC_CRONET_H -#define GRPC_GRPC_CRONET_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( - void *engine, const char *target, const grpc_channel_args *args, - void *reserved); - -#ifdef __cplusplus -} -#endif - -#endif /* GRPC_GRPC_CRONET_H */ diff --git a/package.xml b/package.xml index 716d6ed289..ab6dee0631 100644 --- a/package.xml +++ b/package.xml @@ -176,7 +176,6 @@ - @@ -304,42 +303,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -498,9 +461,6 @@ - - - diff --git a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c deleted file mode 100644 index df1acddcc0..0000000000 --- a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include - -#include -#include - -#include -#include - -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/transport/transport_impl.h" - -// Cronet transport object -typedef struct cronet_transport { - grpc_transport base; // must be first element in this structure - void *engine; - char *host; -} cronet_transport; - -extern grpc_transport_vtable grpc_cronet_vtable; - -GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( - void *engine, const char *target, const grpc_channel_args *args, - void *reserved) { - cronet_transport *ct = gpr_malloc(sizeof(cronet_transport)); - ct->base.vtable = &grpc_cronet_vtable; - ct->engine = engine; - ct->host = gpr_malloc(strlen(target) + 1); - strcpy(ct->host, target); - gpr_log(GPR_DEBUG, - "grpc_create_cronet_transport: cronet_engine = %p, target=%s", engine, - ct->host); - - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - return grpc_channel_create(&exec_ctx, target, args, - GRPC_CLIENT_DIRECT_CHANNEL, (grpc_transport *)ct); -} diff --git a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c deleted file mode 100644 index 687026c9fd..0000000000 --- a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/* This file has empty implementation of all the functions exposed by the cronet -library, so we can build it in all environments */ - -#include - -#include - -#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h" - -#ifdef GRPC_COMPILE_WITH_CRONET -/* link with the real CRONET library in the build system */ -#else -/* Dummy implementation of cronet API just to test for build-ability */ -cronet_bidirectional_stream* cronet_bidirectional_stream_create( - cronet_engine* engine, void* annotation, - cronet_bidirectional_stream_callback* callback) { - GPR_ASSERT(0); - return NULL; -} - -int cronet_bidirectional_stream_destroy(cronet_bidirectional_stream* stream) { - GPR_ASSERT(0); - return 0; -} - -int cronet_bidirectional_stream_start( - cronet_bidirectional_stream* stream, const char* url, int priority, - const char* method, const cronet_bidirectional_stream_header_array* headers, - bool end_of_stream) { - GPR_ASSERT(0); - return 0; -} - -int cronet_bidirectional_stream_read(cronet_bidirectional_stream* stream, - char* buffer, int capacity) { - GPR_ASSERT(0); - return 0; -} - -int cronet_bidirectional_stream_write(cronet_bidirectional_stream* stream, - const char* buffer, int count, - bool end_of_stream) { - GPR_ASSERT(0); - return 0; -} - -int cronet_bidirectional_stream_cancel(cronet_bidirectional_stream* stream) { - GPR_ASSERT(0); - return 0; -} - -#endif /* GRPC_COMPILE_WITH_CRONET */ diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c deleted file mode 100644 index 5bb085195c..0000000000 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ /dev/null @@ -1,640 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/support/string.h" -#include "src/core/lib/surface/channel.h" -#include "src/core/lib/transport/metadata_batch.h" -#include "src/core/lib/transport/transport_impl.h" -#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h" - -#define GRPC_HEADER_SIZE_IN_BYTES 5 - -// Global flag that gets set with GRPC_TRACE env variable -int grpc_cronet_trace = 1; - -// Cronet transport object -struct grpc_cronet_transport { - grpc_transport base; /* must be first element in this structure */ - cronet_engine *engine; - char *host; -}; - -typedef struct grpc_cronet_transport grpc_cronet_transport; - -enum send_state { - CRONET_SEND_IDLE = 0, - CRONET_REQ_STARTED, - CRONET_SEND_HEADER, - CRONET_WRITE, - CRONET_WRITE_COMPLETED, -}; - -enum recv_state { - CRONET_RECV_IDLE = 0, - CRONET_RECV_READ_LENGTH, - CRONET_RECV_READ_DATA, - CRONET_RECV_CLOSED, -}; - -static const char *recv_state_name[] = { - "CRONET_RECV_IDLE", "CRONET_RECV_READ_LENGTH", "CRONET_RECV_READ_DATA,", - "CRONET_RECV_CLOSED"}; - -// Enum that identifies calling function. -enum e_caller { - PERFORM_STREAM_OP, - ON_READ_COMPLETE, - ON_RESPONSE_HEADERS_RECEIVED, - ON_RESPONSE_TRAILERS_RECEIVED -}; - -enum callback_id { - CB_SEND_INITIAL_METADATA = 0, - CB_SEND_MESSAGE, - CB_SEND_TRAILING_METADATA, - CB_RECV_MESSAGE, - CB_RECV_INITIAL_METADATA, - CB_RECV_TRAILING_METADATA, - CB_NUM_CALLBACKS -}; - -struct stream_obj { - // we store received bytes here as they trickle in. - gpr_slice_buffer write_slice_buffer; - cronet_bidirectional_stream *cbs; - gpr_slice slice; - gpr_slice_buffer read_slice_buffer; - struct grpc_slice_buffer_stream sbs; - char *read_buffer; - int remaining_read_bytes; - int total_read_bytes; - - char *write_buffer; - size_t write_buffer_size; - - // Hold the URL - char *url; - - bool response_headers_received; - bool read_requested; - bool response_trailers_received; - bool read_closed; - - // Recv message stuff - grpc_byte_buffer **recv_message; - // Initial metadata stuff - grpc_metadata_batch *recv_initial_metadata; - // Trailing metadata stuff - grpc_metadata_batch *recv_trailing_metadata; - grpc_chttp2_incoming_metadata_buffer imb; - - // This mutex protects receive state machine execution - gpr_mu recv_mu; - // we can queue up up to 2 callbacks for each OP - grpc_closure *callback_list[CB_NUM_CALLBACKS][2]; - - // storage for header - cronet_bidirectional_stream_header *headers; - uint32_t num_headers; - cronet_bidirectional_stream_header_array header_array; - // state tracking - enum recv_state cronet_recv_state; - enum send_state cronet_send_state; -}; - -typedef struct stream_obj stream_obj; - -static void next_send_step(stream_obj *s); -static void next_recv_step(stream_obj *s, enum e_caller caller); - -static void set_pollset_do_nothing(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, grpc_pollset *pollset) {} - -static void enqueue_callbacks(grpc_closure *callback_list[]) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - if (callback_list[0]) { - grpc_exec_ctx_enqueue(&exec_ctx, callback_list[0], true, NULL); - callback_list[0] = NULL; - } - if (callback_list[1]) { - grpc_exec_ctx_enqueue(&exec_ctx, callback_list[1], true, NULL); - callback_list[1] = NULL; - } - grpc_exec_ctx_finish(&exec_ctx); -} - -static void on_canceled(cronet_bidirectional_stream *stream) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "on_canceled %p", stream); - } -} - -static void on_failed(cronet_bidirectional_stream *stream, int net_error) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "on_failed %p, error = %d", stream, net_error); - } -} - -static void on_succeeded(cronet_bidirectional_stream *stream) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "on_succeeded %p", stream); - } -} - -static void on_response_trailers_received( - cronet_bidirectional_stream *stream, - const cronet_bidirectional_stream_header_array *trailers) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: on_response_trailers_received"); - } - stream_obj *s = (stream_obj *)stream->annotation; - - memset(&s->imb, 0, sizeof(s->imb)); - grpc_chttp2_incoming_metadata_buffer_init(&s->imb); - unsigned int i = 0; - for (i = 0; i < trailers->count; i++) { - grpc_chttp2_incoming_metadata_buffer_add( - &s->imb, grpc_mdelem_from_metadata_strings( - grpc_mdstr_from_string(trailers->headers[i].key), - grpc_mdstr_from_string(trailers->headers[i].value))); - } - s->response_trailers_received = true; - next_recv_step(s, ON_RESPONSE_TRAILERS_RECEIVED); -} - -static void on_write_completed(cronet_bidirectional_stream *stream, - const char *data) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "W: on_write_completed"); - } - stream_obj *s = (stream_obj *)stream->annotation; - enqueue_callbacks(s->callback_list[CB_SEND_MESSAGE]); - s->cronet_send_state = CRONET_WRITE_COMPLETED; - next_send_step(s); -} - -static void process_recv_message(stream_obj *s, const uint8_t *recv_data) { - gpr_slice read_data_slice = gpr_slice_malloc((uint32_t)s->total_read_bytes); - uint8_t *dst_p = GPR_SLICE_START_PTR(read_data_slice); - memcpy(dst_p, recv_data, (size_t)s->total_read_bytes); - gpr_slice_buffer_add(&s->read_slice_buffer, read_data_slice); - grpc_slice_buffer_stream_init(&s->sbs, &s->read_slice_buffer, 0); - *s->recv_message = (grpc_byte_buffer *)&s->sbs; -} - -static int parse_grpc_header(const uint8_t *data) { - const uint8_t *p = data + 1; - int length = 0; - length |= ((uint8_t)*p++) << 24; - length |= ((uint8_t)*p++) << 16; - length |= ((uint8_t)*p++) << 8; - length |= ((uint8_t)*p++); - return length; -} - -static void on_read_completed(cronet_bidirectional_stream *stream, char *data, - int count) { - stream_obj *s = (stream_obj *)stream->annotation; - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: on_read_completed count=%d, total=%d, remaining=%d", - count, s->total_read_bytes, s->remaining_read_bytes); - } - if (count > 0) { - GPR_ASSERT(s->recv_message); - s->remaining_read_bytes -= count; - next_recv_step(s, ON_READ_COMPLETE); - } else { - s->read_closed = true; - next_recv_step(s, ON_READ_COMPLETE); - } -} - -static void on_response_headers_received( - cronet_bidirectional_stream *stream, - const cronet_bidirectional_stream_header_array *headers, - const char *negotiated_protocol) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: on_response_headers_received"); - } - stream_obj *s = (stream_obj *)stream->annotation; - enqueue_callbacks(s->callback_list[CB_RECV_INITIAL_METADATA]); - s->response_headers_received = true; - next_recv_step(s, ON_RESPONSE_HEADERS_RECEIVED); -} - -static void on_request_headers_sent(cronet_bidirectional_stream *stream) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "W: on_request_headers_sent"); - } - stream_obj *s = (stream_obj *)stream->annotation; - enqueue_callbacks(s->callback_list[CB_SEND_INITIAL_METADATA]); - s->cronet_send_state = CRONET_SEND_HEADER; - next_send_step(s); -} - -// Callback function pointers (invoked by cronet in response to events) -static cronet_bidirectional_stream_callback callbacks = { - on_request_headers_sent, - on_response_headers_received, - on_read_completed, - on_write_completed, - on_response_trailers_received, - on_succeeded, - on_failed, - on_canceled}; - -static void invoke_closing_callback(stream_obj *s) { - grpc_chttp2_incoming_metadata_buffer_publish(&s->imb, - s->recv_trailing_metadata); - if (s->callback_list[CB_RECV_TRAILING_METADATA]) { - enqueue_callbacks(s->callback_list[CB_RECV_TRAILING_METADATA]); - } -} - -static void set_recv_state(stream_obj *s, enum recv_state state) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "next_state = %s", recv_state_name[state]); - } - s->cronet_recv_state = state; -} - -// This is invoked from perform_stream_op, and all on_xxxx callbacks. -static void next_recv_step(stream_obj *s, enum e_caller caller) { - gpr_mu_lock(&s->recv_mu); - switch (s->cronet_recv_state) { - case CRONET_RECV_IDLE: - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_IDLE"); - } - if (caller == PERFORM_STREAM_OP || - caller == ON_RESPONSE_HEADERS_RECEIVED) { - if (s->read_closed && s->response_trailers_received) { - invoke_closing_callback(s); - set_recv_state(s, CRONET_RECV_CLOSED); - } else if (s->response_headers_received == true && - s->read_requested == true) { - set_recv_state(s, CRONET_RECV_READ_LENGTH); - s->total_read_bytes = s->remaining_read_bytes = - GRPC_HEADER_SIZE_IN_BYTES; - GPR_ASSERT(s->read_buffer); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()"); - } - cronet_bidirectional_stream_read(s->cbs, s->read_buffer, - s->remaining_read_bytes); - } - } - break; - case CRONET_RECV_READ_LENGTH: - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_LENGTH"); - } - if (caller == ON_READ_COMPLETE) { - if (s->read_closed) { - invoke_closing_callback(s); - enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]); - set_recv_state(s, CRONET_RECV_CLOSED); - } else { - GPR_ASSERT(s->remaining_read_bytes == 0); - set_recv_state(s, CRONET_RECV_READ_DATA); - s->total_read_bytes = s->remaining_read_bytes = - parse_grpc_header((const uint8_t *)s->read_buffer); - s->read_buffer = - gpr_realloc(s->read_buffer, (uint32_t)s->remaining_read_bytes); - GPR_ASSERT(s->read_buffer); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()"); - } - cronet_bidirectional_stream_read(s->cbs, (char *)s->read_buffer, - s->remaining_read_bytes); - } - } - break; - case CRONET_RECV_READ_DATA: - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_DATA"); - } - if (caller == ON_READ_COMPLETE) { - if (s->remaining_read_bytes > 0) { - int offset = s->total_read_bytes - s->remaining_read_bytes; - GPR_ASSERT(s->read_buffer); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()"); - } - cronet_bidirectional_stream_read( - s->cbs, (char *)s->read_buffer + offset, s->remaining_read_bytes); - } else { - gpr_slice_buffer_init(&s->read_slice_buffer); - uint8_t *p = (uint8_t *)s->read_buffer; - process_recv_message(s, p); - set_recv_state(s, CRONET_RECV_IDLE); - enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]); - } - } - break; - case CRONET_RECV_CLOSED: - break; - default: - GPR_ASSERT(0); // Should not reach here - break; - } - gpr_mu_unlock(&s->recv_mu); -} - -// This function takes the data from s->write_slice_buffer and assembles into -// a contiguous byte stream with 5 byte gRPC header prepended. -static void create_grpc_frame(stream_obj *s) { - gpr_slice slice = gpr_slice_buffer_take_first(&s->write_slice_buffer); - uint8_t *raw_data = GPR_SLICE_START_PTR(slice); - size_t length = GPR_SLICE_LENGTH(slice); - s->write_buffer_size = length + GRPC_HEADER_SIZE_IN_BYTES; - s->write_buffer = gpr_realloc(s->write_buffer, s->write_buffer_size); - uint8_t *p = (uint8_t *)s->write_buffer; - // Append 5 byte header - *p++ = 0; - *p++ = (uint8_t)(length >> 24); - *p++ = (uint8_t)(length >> 16); - *p++ = (uint8_t)(length >> 8); - *p++ = (uint8_t)(length); - // append actual data - memcpy(p, raw_data, length); -} - -static void do_write(stream_obj *s) { - gpr_slice_buffer *sb = &s->write_slice_buffer; - GPR_ASSERT(sb->count <= 1); - if (sb->count > 0) { - create_grpc_frame(s); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write"); - } - cronet_bidirectional_stream_write(s->cbs, s->write_buffer, - (int)s->write_buffer_size, false); - } -} - -// -static void next_send_step(stream_obj *s) { - switch (s->cronet_send_state) { - case CRONET_SEND_IDLE: - GPR_ASSERT( - s->cbs); // cronet_bidirectional_stream is not initialized yet. - s->cronet_send_state = CRONET_REQ_STARTED; - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_start to %s", s->url); - } - cronet_bidirectional_stream_start(s->cbs, s->url, 0, "POST", - &s->header_array, false); - // we no longer need the memory that was allocated earlier. - gpr_free(s->header_array.headers); - break; - case CRONET_SEND_HEADER: - do_write(s); - s->cronet_send_state = CRONET_WRITE; - break; - case CRONET_WRITE_COMPLETED: - do_write(s); - break; - default: - GPR_ASSERT(0); - break; - } -} - -static void convert_metadata_to_cronet_headers(grpc_linked_mdelem *head, - const char *host, - stream_obj *s) { - grpc_linked_mdelem *curr = head; - // Walk the linked list and get number of header fields - uint32_t num_headers_available = 0; - while (curr != NULL) { - curr = curr->next; - num_headers_available++; - } - // Allocate enough memory - s->headers = (cronet_bidirectional_stream_header *)gpr_malloc( - sizeof(cronet_bidirectional_stream_header) * num_headers_available); - - // Walk the linked list again, this time copying the header fields. - // s->num_headers - // can be less than num_headers_available, as some headers are not used for - // cronet - curr = head; - s->num_headers = 0; - while (s->num_headers < num_headers_available) { - grpc_mdelem *mdelem = curr->md; - curr = curr->next; - const char *key = grpc_mdstr_as_c_string(mdelem->key); - const char *value = grpc_mdstr_as_c_string(mdelem->value); - if (strcmp(key, ":scheme") == 0 || strcmp(key, ":method") == 0 || - strcmp(key, ":authority") == 0) { - // Cronet populates these fields on its own. - continue; - } - if (strcmp(key, ":path") == 0) { - // Create URL by appending :path value to the hostname - gpr_asprintf(&s->url, "https://%s%s", host, value); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "extracted URL = %s", s->url); - } - continue; - } - s->headers[s->num_headers].key = key; - s->headers[s->num_headers].value = value; - s->num_headers++; - if (curr == NULL) { - break; - } - } -} - -static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, grpc_transport_stream_op *op) { - grpc_cronet_transport *ct = (grpc_cronet_transport *)gt; - GPR_ASSERT(ct->engine); - stream_obj *s = (stream_obj *)gs; - if (op->recv_trailing_metadata) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, - "perform_stream_op - recv_trailing_metadata: on_complete=%p", - op->on_complete); - } - s->recv_trailing_metadata = op->recv_trailing_metadata; - GPR_ASSERT(!s->callback_list[CB_RECV_TRAILING_METADATA][0]); - s->callback_list[CB_RECV_TRAILING_METADATA][0] = op->on_complete; - } - if (op->recv_message) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "perform_stream_op - recv_message: on_complete=%p", - op->on_complete); - } - s->recv_message = (grpc_byte_buffer **)op->recv_message; - GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][0]); - GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][1]); - s->callback_list[CB_RECV_MESSAGE][0] = op->recv_message_ready; - s->callback_list[CB_RECV_MESSAGE][1] = op->on_complete; - s->read_requested = true; - next_recv_step(s, PERFORM_STREAM_OP); - } - if (op->recv_initial_metadata) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "perform_stream_op - recv_initial_metadata:=%p", - op->on_complete); - } - s->recv_initial_metadata = op->recv_initial_metadata; - GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][0]); - GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][1]); - s->callback_list[CB_RECV_INITIAL_METADATA][0] = - op->recv_initial_metadata_ready; - s->callback_list[CB_RECV_INITIAL_METADATA][1] = op->on_complete; - } - if (op->send_initial_metadata) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, - "perform_stream_op - send_initial_metadata: on_complete=%p", - op->on_complete); - } - s->num_headers = 0; - convert_metadata_to_cronet_headers(op->send_initial_metadata->list.head, - ct->host, s); - s->header_array.count = s->num_headers; - s->header_array.capacity = s->num_headers; - s->header_array.headers = s->headers; - GPR_ASSERT(!s->callback_list[CB_SEND_INITIAL_METADATA][0]); - s->callback_list[CB_SEND_INITIAL_METADATA][0] = op->on_complete; - } - if (op->send_message) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "perform_stream_op - send_message: on_complete=%p", - op->on_complete); - } - grpc_byte_stream_next(exec_ctx, op->send_message, &s->slice, - op->send_message->length, NULL); - // Check that compression flag is not ON. We don't support compression yet. - // TODO (makdharma): add compression support - GPR_ASSERT(op->send_message->flags == 0); - gpr_slice_buffer_add(&s->write_slice_buffer, s->slice); - if (s->cbs == NULL) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_create"); - } - s->cbs = cronet_bidirectional_stream_create(ct->engine, s, &callbacks); - GPR_ASSERT(s->cbs); - s->read_closed = false; - s->response_trailers_received = false; - s->response_headers_received = false; - s->cronet_send_state = CRONET_SEND_IDLE; - s->cronet_recv_state = CRONET_RECV_IDLE; - } - GPR_ASSERT(!s->callback_list[CB_SEND_MESSAGE][0]); - s->callback_list[CB_SEND_MESSAGE][0] = op->on_complete; - next_send_step(s); - } - if (op->send_trailing_metadata) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, - "perform_stream_op - send_trailing_metadata: on_complete=%p", - op->on_complete); - } - GPR_ASSERT(!s->callback_list[CB_SEND_TRAILING_METADATA][0]); - s->callback_list[CB_SEND_TRAILING_METADATA][0] = op->on_complete; - if (s->cbs) { - // Send an "empty" write to the far end to signal that we're done. - // This will induce the server to send down trailers. - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write"); - } - cronet_bidirectional_stream_write(s->cbs, "abc", 0, true); - } else { - // We never created a stream. This was probably an empty request. - invoke_closing_callback(s); - } - } -} - -static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, grpc_stream_refcount *refcount, - const void *server_data) { - stream_obj *s = (stream_obj *)gs; - memset(s->callback_list, 0, sizeof(s->callback_list)); - s->cbs = NULL; - gpr_mu_init(&s->recv_mu); - s->read_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES); - s->write_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES); - gpr_slice_buffer_init(&s->write_slice_buffer); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "cronet_transport - init_stream"); - } - return 0; -} - -static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, - grpc_stream *gs, void *and_free_memory) { - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "Destroy stream"); - } - stream_obj *s = (stream_obj *)gs; - s->cbs = NULL; - gpr_free(s->read_buffer); - gpr_free(s->write_buffer); - gpr_free(s->url); - gpr_mu_destroy(&s->recv_mu); - if (and_free_memory) { - gpr_free(and_free_memory); - } -} - -static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { - grpc_cronet_transport *ct = (grpc_cronet_transport *)gt; - gpr_free(ct->host); - if (grpc_cronet_trace) { - gpr_log(GPR_DEBUG, "Destroy transport"); - } -} - -const grpc_transport_vtable grpc_cronet_vtable = { - sizeof(stream_obj), "cronet_http", init_stream, - set_pollset_do_nothing, perform_stream_op, NULL, - destroy_stream, destroy_transport, NULL}; diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c index 09551472b5..f0a40dbb35 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.c +++ b/src/python/grpcio/grpc/_cython/imports.generated.c @@ -125,7 +125,6 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; -grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -396,7 +395,6 @@ void pygrpc_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); - grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h index 54c8aaad13..d5e810b7cf 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/python/grpcio/grpc/_cython/imports.generated.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -326,9 +325,6 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import -typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); -extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; -#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 5314329c2c..dab62530aa 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -222,9 +222,6 @@ CORE_SOURCE_FILES = [ 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', - 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', - 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', - 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index cebbe8c40f..bc43f9d36b 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -125,7 +125,6 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; -grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -392,7 +391,6 @@ void grpc_rb_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); - grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index d7ea6c574c..b67361ca25 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -326,9 +325,6 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import -typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); -extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; -#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index fd6ff2c26f..3eeb55d033 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include diff --git a/third_party/objective_c/Cronet/cronet_c_for_grpc.h b/third_party/objective_c/Cronet/cronet_c_for_grpc.h deleted file mode 100644 index 15a511aebd..0000000000 --- a/third_party/objective_c/Cronet/cronet_c_for_grpc.h +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ -#define COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* Cronet Engine API. */ - -/* Opaque object representing Cronet Engine. Created and configured outside - * of this API to facilitate sharing with other components */ -typedef struct cronet_engine { void* obj; } cronet_engine; - -void cronet_engine_add_quic_hint(cronet_engine* engine, - const char* host, - int port, - int alternate_port); - -/* Cronet Bidirectional Stream API */ - -/* Opaque object representing Cronet Bidirectional Stream. */ -typedef struct cronet_bidirectional_stream { - void* obj; - void* annotation; -} cronet_bidirectional_stream; - -/* A single request or response header element. */ -typedef struct cronet_bidirectional_stream_header { - const char* key; - const char* value; -} cronet_bidirectional_stream_header; - -/* Array of request or response headers or trailers. */ -typedef struct cronet_bidirectional_stream_header_array { - size_t count; - size_t capacity; - cronet_bidirectional_stream_header* headers; -} cronet_bidirectional_stream_header_array; - -/* Set of callbacks used to receive callbacks from bidirectional stream. */ -typedef struct cronet_bidirectional_stream_callback { - /* Invoked when request headers are sent. Indicates that stream has initiated - * the request. Consumer may call cronet_bidirectional_stream_write() to start - * writing data. - */ - void (*on_request_headers_sent)(cronet_bidirectional_stream* stream); - - /* Invoked when initial response headers are received. - * Consumer must call cronet_bidirectional_stream_read() to start reading. - * Consumer may call cronet_bidirectional_stream_write() to start writing or - * close the stream. Contents of |headers| is valid for duration of the call. - */ - void (*on_response_headers_received)( - cronet_bidirectional_stream* stream, - const cronet_bidirectional_stream_header_array* headers, - const char* negotiated_protocol); - - /* Invoked when data is read into the buffer passed to - * cronet_bidirectional_stream_read(). Only part of the buffer may be - * populated. To continue reading, call cronet_bidirectional_stream_read(). - * It may be invoked after on_response_trailers_received()}, if there was - * pending read data before trailers were received. - * - * If count is 0, it means the remote side has signaled that it will send no - * more data; future calls to cronet_bidirectional_stream_read() will result - * in the on_data_read() callback or on_succeded() callback if - * cronet_bidirectional_stream_write() was invoked with end_of_stream set to - * true. - */ - void (*on_read_completed)(cronet_bidirectional_stream* stream, - char* data, - int count); - - /** - * Invoked when all data passed to cronet_bidirectional_stream_write() is - * sent. - * To continue writing, call cronet_bidirectional_stream_write(). - */ - void (*on_write_completed)(cronet_bidirectional_stream* stream, - const char* data); - - /* Invoked when trailers are received before closing the stream. Only invoked - * when server sends trailers, which it may not. May be invoked while there is - * read data remaining in local buffer. Contents of |trailers| is valid for - * duration of the call. - */ - void (*on_response_trailers_received)( - cronet_bidirectional_stream* stream, - const cronet_bidirectional_stream_header_array* trailers); - - /** - * Invoked when there is no data to be read or written and the stream is - * closed successfully remotely and locally. Once invoked, no further callback - * methods will be invoked. - */ - void (*on_succeded)(cronet_bidirectional_stream* stream); - - /** - * Invoked if the stream failed for any reason after - * cronet_bidirectional_stream_start(). HTTP/2 error codes are - * mapped to chrome net error codes. Once invoked, no further callback methods - * will be invoked. - */ - void (*on_failed)(cronet_bidirectional_stream* stream, int net_error); - - /** - * Invoked if the stream was canceled via - * cronet_bidirectional_stream_cancel(). Once invoked, no further callback - * methods will be invoked. - */ - void (*on_canceled)(cronet_bidirectional_stream* stream); -} cronet_bidirectional_stream_callback; - -/* Create a new stream object that uses |engine| and |callback|. All stream - * tasks are performed asynchronously on the |engine| network thread. |callback| - * methods are invoked synchronously on the |engine| network thread, but must - * not run tasks on the current thread to prevent blocking networking operations - * and causing exceptions during shutdown. The |annotation| is stored in - * bidirectional stream for arbitrary use by application. - * - * Returned |cronet_bidirectional_stream*| is owned by the caller, and must be - * destroyed using |cronet_bidirectional_stream_destroy|. - * - * Both |calback| and |engine| must remain valid until stream is destroyed. - */ -cronet_bidirectional_stream* cronet_bidirectional_stream_create( - cronet_engine* engine, - void* annotation, - cronet_bidirectional_stream_callback* callback); - -/* TBD: The following methods return int. Should it be a custom type? */ - -/* Destroy stream object. Destroy could be called from any thread, including - * network thread, but is posted, so |stream| is valid until calling task is - * complete. - */ -int cronet_bidirectional_stream_destroy(cronet_bidirectional_stream* stream); - -/* Start the stream by sending request to |url| using |method| and |headers|. If - * |end_of_stream| is true, then no data is expected to be written. - */ -int cronet_bidirectional_stream_start( - cronet_bidirectional_stream* stream, - const char* url, - int priority, - const char* method, - const cronet_bidirectional_stream_header_array* headers, - bool end_of_stream); - -/* Read response data into |buffer| of |capacity| length. Must only be called at - * most once in response to each invocation of the - * on_response_headers_received() and on_read_completed() methods of the - * cronet_bidirectional_stream_callback. - * Each call will result in an invocation of one of the callback's - * on_read_completed method if data is read, its on_succeeded() method if - * the stream is closed, or its on_failed() method if there's an error. - */ -int cronet_bidirectional_stream_read(cronet_bidirectional_stream* stream, - char* buffer, - int capacity); - -/* Read response data into |buffer| of |capacity| length. Must only be called at - * most once in response to each invocation of the - * on_response_headers_received() and on_read_completed() methods of the - * cronet_bidirectional_stream_callback. - * Each call will result in an invocation of one of the callback's - * on_read_completed method if data is read, its on_succeeded() method if - * the stream is closed, or its on_failed() method if there's an error. - */ -int cronet_bidirectional_stream_write(cronet_bidirectional_stream* stream, - const char* buffer, - int count, - bool end_of_stream); - -/* Cancels the stream. Can be called at any time after - * cronet_bidirectional_stream_start(). The on_canceled() method of - * cronet_bidirectional_stream_callback will be invoked when cancelation - * is complete and no further callback methods will be invoked. If the - * stream has completed or has not started, calling - * cronet_bidirectional_stream_cancel() has no effect and on_canceled() will not - * be invoked. At most one callback method may be invoked after - * cronet_bidirectional_stream_cancel() has completed. - */ -int cronet_bidirectional_stream_cancel(cronet_bidirectional_stream* stream); - -/* Returns true if the |stream| was successfully started and is now done - * (succeeded, canceled, or failed). - * Returns false if the |stream| stream is not yet started or is in progress. - */ -bool cronet_bidirectional_stream_is_done(cronet_bidirectional_stream* stream); - -#ifdef __cplusplus -} -#endif - -#endif // COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index d1259e7aee..8b13e6e793 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -786,7 +786,6 @@ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ -include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 6b7a8be861..b3b3477874 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -786,7 +786,6 @@ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ -include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -914,42 +913,6 @@ src/core/ext/client_config/subchannel.h \ src/core/ext/client_config/subchannel_call_holder.h \ src/core/ext/client_config/subchannel_index.h \ src/core/ext/client_config/uri_parser.h \ -include/grpc/byte_buffer.h \ -include/grpc/grpc.h \ -include/grpc/impl/codegen/alloc.h \ -include/grpc/impl/codegen/atm.h \ -include/grpc/impl/codegen/atm_gcc_atomic.h \ -include/grpc/impl/codegen/atm_gcc_sync.h \ -include/grpc/impl/codegen/atm_win32.h \ -include/grpc/impl/codegen/byte_buffer.h \ -include/grpc/impl/codegen/compression_types.h \ -include/grpc/impl/codegen/connectivity_state.h \ -include/grpc/impl/codegen/grpc_types.h \ -include/grpc/impl/codegen/log.h \ -include/grpc/impl/codegen/port_platform.h \ -include/grpc/impl/codegen/propagation_bits.h \ -include/grpc/impl/codegen/slice.h \ -include/grpc/impl/codegen/slice_buffer.h \ -include/grpc/impl/codegen/status.h \ -include/grpc/impl/codegen/sync.h \ -include/grpc/impl/codegen/sync_generic.h \ -include/grpc/impl/codegen/sync_posix.h \ -include/grpc/impl/codegen/sync_win32.h \ -include/grpc/impl/codegen/time.h \ -include/grpc/status.h \ -include/grpc/support/alloc.h \ -include/grpc/support/atm.h \ -include/grpc/support/host_port.h \ -include/grpc/support/log.h \ -include/grpc/support/port_platform.h \ -include/grpc/support/slice.h \ -include/grpc/support/slice_buffer.h \ -include/grpc/support/string_util.h \ -include/grpc/support/sync.h \ -include/grpc/support/time.h \ -include/grpc/support/useful.h \ -src/core/lib/support/string.h \ -third_party/objective_c/Cronet/cronet_c_for_grpc.h \ src/core/ext/lb_policy/grpclb/load_balancer_api.h \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h \ third_party/nanopb/pb.h \ @@ -1108,9 +1071,6 @@ src/core/ext/client_config/subchannel_index.c \ src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ -src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ -src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ -src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 8c67d2f844..3b3a49a5b2 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -4140,8 +4140,7 @@ "grpc_transport_chttp2_client_insecure", "grpc_transport_chttp2_client_secure", "grpc_transport_chttp2_server_insecure", - "grpc_transport_chttp2_server_secure", - "grpc_transport_cronet_client_secure" + "grpc_transport_chttp2_server_secure" ], "headers": [], "language": "c", @@ -6015,7 +6014,6 @@ "tsi" ], "headers": [ - "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "src/core/lib/security/auth_filters.h", @@ -6031,7 +6029,6 @@ "language": "c", "name": "grpc_secure", "src": [ - "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "src/core/lib/http/httpcli_security_connector.c", @@ -6267,121 +6264,6 @@ "third_party": false, "type": "filegroup" }, - { - "deps": [], - "headers": [ - "include/grpc/byte_buffer.h", - "include/grpc/grpc.h", - "include/grpc/impl/codegen/alloc.h", - "include/grpc/impl/codegen/atm.h", - "include/grpc/impl/codegen/atm_gcc_atomic.h", - "include/grpc/impl/codegen/atm_gcc_sync.h", - "include/grpc/impl/codegen/atm_win32.h", - "include/grpc/impl/codegen/byte_buffer.h", - "include/grpc/impl/codegen/compression_types.h", - "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/grpc_types.h", - "include/grpc/impl/codegen/log.h", - "include/grpc/impl/codegen/port_platform.h", - "include/grpc/impl/codegen/propagation_bits.h", - "include/grpc/impl/codegen/slice.h", - "include/grpc/impl/codegen/slice_buffer.h", - "include/grpc/impl/codegen/status.h", - "include/grpc/impl/codegen/sync.h", - "include/grpc/impl/codegen/sync_generic.h", - "include/grpc/impl/codegen/sync_posix.h", - "include/grpc/impl/codegen/sync_win32.h", - "include/grpc/impl/codegen/time.h", - "include/grpc/status.h", - "include/grpc/support/alloc.h", - "include/grpc/support/atm.h", - "include/grpc/support/host_port.h", - "include/grpc/support/log.h", - "include/grpc/support/port_platform.h", - "include/grpc/support/slice.h", - "include/grpc/support/slice_buffer.h", - "include/grpc/support/string_util.h", - "include/grpc/support/sync.h", - "include/grpc/support/time.h", - "include/grpc/support/useful.h", - "src/core/ext/transport/chttp2/transport/incoming_metadata.h", - "src/core/lib/channel/channel_stack.h", - "src/core/lib/channel/context.h", - "src/core/lib/debug/trace.h", - "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/exec_ctx.h", - "src/core/lib/iomgr/pollset.h", - "src/core/lib/iomgr/pollset_set.h", - "src/core/lib/support/string.h", - "src/core/lib/surface/channel.h", - "src/core/lib/surface/channel_stack_type.h", - "src/core/lib/transport/byte_stream.h", - "src/core/lib/transport/metadata.h", - "src/core/lib/transport/metadata_batch.h", - "src/core/lib/transport/transport.h", - "src/core/lib/transport/transport_impl.h", - "third_party/objective_c/Cronet/cronet_c_for_grpc.h" - ], - "language": "c", - "name": "grpc_transport_cronet_client_secure", - "src": [ - "include/grpc/byte_buffer.h", - "include/grpc/grpc.h", - "include/grpc/impl/codegen/alloc.h", - "include/grpc/impl/codegen/atm.h", - "include/grpc/impl/codegen/atm_gcc_atomic.h", - "include/grpc/impl/codegen/atm_gcc_sync.h", - "include/grpc/impl/codegen/atm_win32.h", - "include/grpc/impl/codegen/byte_buffer.h", - "include/grpc/impl/codegen/compression_types.h", - "include/grpc/impl/codegen/connectivity_state.h", - "include/grpc/impl/codegen/grpc_types.h", - "include/grpc/impl/codegen/log.h", - "include/grpc/impl/codegen/port_platform.h", - "include/grpc/impl/codegen/propagation_bits.h", - "include/grpc/impl/codegen/slice.h", - "include/grpc/impl/codegen/slice_buffer.h", - "include/grpc/impl/codegen/status.h", - "include/grpc/impl/codegen/sync.h", - "include/grpc/impl/codegen/sync_generic.h", - "include/grpc/impl/codegen/sync_posix.h", - "include/grpc/impl/codegen/sync_win32.h", - "include/grpc/impl/codegen/time.h", - "include/grpc/status.h", - "include/grpc/support/alloc.h", - "include/grpc/support/atm.h", - "include/grpc/support/host_port.h", - "include/grpc/support/log.h", - "include/grpc/support/port_platform.h", - "include/grpc/support/slice.h", - "include/grpc/support/slice_buffer.h", - "include/grpc/support/string_util.h", - "include/grpc/support/sync.h", - "include/grpc/support/time.h", - "include/grpc/support/useful.h", - "src/core/ext/transport/chttp2/transport/incoming_metadata.h", - "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", - "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", - "src/core/ext/transport/cronet/transport/cronet_transport.c", - "src/core/lib/channel/channel_stack.h", - "src/core/lib/channel/context.h", - "src/core/lib/debug/trace.h", - "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/exec_ctx.h", - "src/core/lib/iomgr/pollset.h", - "src/core/lib/iomgr/pollset_set.h", - "src/core/lib/support/string.h", - "src/core/lib/surface/channel.h", - "src/core/lib/surface/channel_stack_type.h", - "src/core/lib/transport/byte_stream.h", - "src/core/lib/transport/metadata.h", - "src/core/lib/transport/metadata_batch.h", - "src/core/lib/transport/transport.h", - "src/core/lib/transport/transport_impl.h" - ], - "third_party": false, - "type": "filegroup" - }, { "deps": [], "headers": [ diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 7f0e5a8339..03f4eaa5be 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -293,7 +293,6 @@ - @@ -423,42 +422,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -765,12 +728,6 @@ - - - - - - diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 6d1d69a913..4617e3de0d 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -439,15 +439,6 @@ src\core\ext\transport\chttp2\client\insecure - - src\core\ext\transport\cronet\client\secure - - - src\core\ext\transport\cronet\transport - - - src\core\ext\transport\cronet\transport - src\core\ext\lb_policy\grpclb @@ -585,9 +576,6 @@ include\grpc\impl\codegen - - include\grpc - include\grpc @@ -971,114 +959,6 @@ src\core\ext\client_config - - include\grpc - - - include\grpc - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc\impl\codegen - - - include\grpc - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - include\grpc\support - - - src\core\lib\support - - - third_party\objective_c\Cronet - src\core\ext\lb_policy\grpclb @@ -1130,9 +1010,6 @@ {def748f5-ed2a-a9bb-40d9-c31d00f0e13b} - - {31de82ea-dc6c-73fb-a640-979b8a7b240c} - {d538af37-07b2-062b-fa2a-d9f882cb2737} @@ -1214,18 +1091,6 @@ {6f34254e-e69f-c9b4-156d-5024bade5408} - - {1e9c85e9-5522-7ef8-0017-7e19990a6194} - - - {d0530883-75d9-b5f7-d594-26735a70ac7b} - - - {4fa6fe90-b7a8-5c8f-d629-db1e68d89eed} - - - {31518af8-5860-6d0d-ff78-4059fce29ec2} - {5b2ded3f-84a5-f6b4-2060-286c7d1dc945} @@ -1250,9 +1115,6 @@ {c4661d64-349f-01c1-1ba8-0602f9047595} - - {27f30339-d694-40f5-db07-4b89b9aeea73} - {a21971fb-304f-da08-b1b2-7bd8df8ac373} @@ -1271,12 +1133,6 @@ {93d6596d-330c-1d27-6f84-3c840e57869e} - - {3a56a516-857e-d2aa-95cc-11685baf4e8c} - - - {a165c6e3-0776-6f40-7351-d7865668e220} - -- cgit v1.2.3 From 1eb8d54a1967edbc234d8abae5b1c4216c8bd867 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Tue, 10 May 2016 16:57:14 -0700 Subject: Added true async qps client --- src/python/grpcio/tests/qps/benchmark_client.py | 60 ++++++++++++++++++++++--- src/python/grpcio/tests/qps/client_runner.py | 2 +- src/python/grpcio/tests/qps/worker_server.py | 5 ++- tools/run_tests/performance/scenario_config.py | 49 ++++++++++---------- 4 files changed, 81 insertions(+), 35 deletions(-) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/tests/qps/benchmark_client.py b/src/python/grpcio/tests/qps/benchmark_client.py index eed0b0c6da..b372ea01ad 100644 --- a/src/python/grpcio/tests/qps/benchmark_client.py +++ b/src/python/grpcio/tests/qps/benchmark_client.py @@ -39,6 +39,7 @@ except ImportError: from concurrent import futures from grpc.beta import implementations +from grpc.framework.interfaces.face import face from src.proto.grpc.testing import messages_pb2 from src.proto.grpc.testing import services_pb2 from tests.unit import resources @@ -141,10 +142,10 @@ class UnaryAsyncBenchmarkClient(BenchmarkClient): self._stub = None -class StreamingAsyncBenchmarkClient(BenchmarkClient): +class StreamingSyncBenchmarkClient(BenchmarkClient): def __init__(self, server, config, hist): - super(StreamingAsyncBenchmarkClient, self).__init__(server, config, hist) + super(StreamingSyncBenchmarkClient, self).__init__(server, config, hist) self._is_streaming = False self._pool = futures.ThreadPoolExecutor(max_workers=1) # Use a thread-safe queue to put requests on the stream @@ -167,12 +168,12 @@ class StreamingAsyncBenchmarkClient(BenchmarkClient): def _request_stream(self): self._is_streaming = True if self._generic: - response_stream = self._stub.inline_stream_stream( - 'grpc.testing.BenchmarkService', 'StreamingCall', - self._request_generator(), _TIMEOUT) + stream_callable = self._stub.stream_stream( + 'grpc.testing.BenchmarkService', 'StreamingCall') else: - response_stream = self._stub.StreamingCall(self._request_generator(), - _TIMEOUT) + stream_callable = self._stub.StreamingCall + + response_stream = stream_callable(self._request_generator(), _TIMEOUT) for _ in response_stream: end_time = time.time() self._handle_response(end_time - self._send_time_queue.get_nowait()) @@ -184,3 +185,48 @@ class StreamingAsyncBenchmarkClient(BenchmarkClient): yield request except queue.Empty: pass + + +class AsyncReceiver(face.ResponseReceiver): + """Receiver for async stream responses.""" + + def __init__(self, send_time_queue, response_handler): + self._send_time_queue = send_time_queue + self._response_handler = response_handler + + def initial_metadata(self, initial_mdetadata): + pass + + def response(self, response): + end_time = time.time() + self._response_handler(end_time - self._send_time_queue.get_nowait()) + + def complete(self, terminal_metadata, code, details): + pass + + +class StreamingAsyncBenchmarkClient(BenchmarkClient): + + def __init__(self, server, config, hist): + super(StreamingAsyncBenchmarkClient, self).__init__(server, config, hist) + self._send_time_queue = queue.Queue() + self._receiver = AsyncReceiver(self._send_time_queue, self._handle_response) + self._rendezvous = None + + def send_request(self): + if self._rendezvous is not None: + self._send_time_queue.put(time.time()) + self._rendezvous.consume(self._request) + + def start(self): + if self._generic: + stream_callable = self._stub.stream_stream( + 'grpc.testing.BenchmarkService', 'StreamingCall') + else: + stream_callable = self._stub.StreamingCall + self._rendezvous = stream_callable.event( + self._receiver, lambda *args: None, _TIMEOUT) + + def stop(self): + self._rendezvous.terminate() + self._rendezvous = None diff --git a/src/python/grpcio/tests/qps/client_runner.py b/src/python/grpcio/tests/qps/client_runner.py index a36c30ccc0..1ede7d2af1 100644 --- a/src/python/grpcio/tests/qps/client_runner.py +++ b/src/python/grpcio/tests/qps/client_runner.py @@ -89,9 +89,9 @@ class ClosedLoopClientRunner(ClientRunner): def start(self): self._is_running = True + self._client.start() for _ in xrange(self._request_count): self._client.send_request() - self._client.start() def stop(self): self._is_running = False diff --git a/src/python/grpcio/tests/qps/worker_server.py b/src/python/grpcio/tests/qps/worker_server.py index 0b3acc14e7..1f9af5482c 100644 --- a/src/python/grpcio/tests/qps/worker_server.py +++ b/src/python/grpcio/tests/qps/worker_server.py @@ -146,8 +146,9 @@ class WorkerServer(services_pb2.BetaWorkerServiceServicer): if config.rpc_type == control_pb2.UNARY: client = benchmark_client.UnarySyncBenchmarkClient( server, config, qps_data) - else: - raise Exception('STREAMING SYNC client not supported') + elif config.rpc_type == control_pb2.STREAMING: + client = benchmark_client.StreamingSyncBenchmarkClient( + server, config, qps_data) elif config.client_type == control_pb2.ASYNC_CLIENT: if config.rpc_type == control_pb2.UNARY: client = benchmark_client.UnaryAsyncBenchmarkClient( diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py index d393709623..30db85cf48 100644 --- a/tools/run_tests/performance/scenario_config.py +++ b/tools/run_tests/performance/scenario_config.py @@ -355,39 +355,39 @@ class PythonLanguage: return 500 def scenarios(self): - # TODO(jtattermusch): this scenario reports QPS 0.0 - yield _ping_pong_scenario( - 'python_generic_async_streaming_ping_pong', rpc_type='STREAMING', - client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER', - use_generic_payload=True, - categories=[SMOKETEST]) - - # TODO(jtattermusch): make this scenario work + # TODO(issue #6522): Empty streaming requests does not work for python #yield _ping_pong_scenario( - # 'python_protobuf_async_streaming_ping_pong', rpc_type='STREAMING', - # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER') + # 'python_generic_async_streaming_ping_pong', rpc_type='STREAMING', + # client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER', + # use_generic_payload=True, + # categories=[SMOKETEST]) - # TODO(jtattermusch): make this scenario work - #yield _ping_pong_scenario( - # 'python_protobuf_async_unary_ping_pong', rpc_type='UNARY', - # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER') + yield _ping_pong_scenario( + 'python_protobuf_async_streaming_ping_pong', rpc_type='STREAMING', + client_type='ASYNC_CLIENT', server_type='SYNC_SERVER') + + yield _ping_pong_scenario( + 'python_protobuf_async_unary_ping_pong', rpc_type='UNARY', + client_type='ASYNC_CLIENT', server_type='SYNC_SERVER') yield _ping_pong_scenario( 'python_protobuf_sync_unary_ping_pong', rpc_type='UNARY', client_type='SYNC_CLIENT', server_type='SYNC_SERVER', categories=[SMOKETEST]) - # TODO(jtattermusch): make this scenario work + # TODO(jtattermusch): + # The qps_worker server gets thread starved with ~6400 threads, the GIL + # enforces that a single thread runs at a time, with no way to set thread + # priority. Re-evaluate after changing DEEP and WIDE. #yield _ping_pong_scenario( # 'python_protobuf_sync_unary_qps_unconstrained', rpc_type='UNARY', # client_type='SYNC_CLIENT', server_type='SYNC_SERVER', # use_unconstrained_client=True) - # TODO(jtattermusch): make this scenario work - #yield _ping_pong_scenario( - # 'python_protobuf_async_streaming_qps_unconstrained', rpc_type='STREAMING', - # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER', - # use_unconstrained_client=True) + yield _ping_pong_scenario( + 'python_protobuf_async_streaming_qps_unconstrained', rpc_type='STREAMING', + client_type='ASYNC_CLIENT', server_type='SYNC_SERVER', + use_unconstrained_client=True) yield _ping_pong_scenario( 'python_to_cpp_protobuf_sync_unary_ping_pong', rpc_type='UNARY', @@ -395,11 +395,10 @@ class PythonLanguage: server_language='c++', server_core_limit=1, async_server_threads=1, categories=[SMOKETEST]) - # TODO(jtattermusch): make this scenario work - #yield _ping_pong_scenario( - # 'python_to_cpp_protobuf_sync_streaming_ping_pong', rpc_type='STREAMING', - # client_type='SYNC_CLIENT', server_type='SYNC_SERVER', - # server_language='c++', server_core_limit=1, async_server_threads=1) + yield _ping_pong_scenario( + 'python_to_cpp_protobuf_sync_streaming_ping_pong', rpc_type='STREAMING', + client_type='SYNC_CLIENT', server_type='SYNC_SERVER', + server_language='c++', server_core_limit=1, async_server_threads=1) def __str__(self): return 'python' -- cgit v1.2.3 From c2ec95bad4e279c713555195a7fd3ff6bbcc249e Mon Sep 17 00:00:00 2001 From: makdharma Date: Wed, 11 May 2016 16:26:15 -0700 Subject: Revert "Revert "cronet wrapper code"" --- BUILD | 80 +++ Makefile | 7 + binding.gyp | 3 + build.yaml | 59 ++ config.m4 | 5 + gRPC.podspec | 76 +++ grpc.def | 1 + grpc.gemspec | 40 ++ include/grpc/grpc_cronet.h | 51 ++ package.xml | 40 ++ .../cronet/client/secure/cronet_channel_create.c | 69 +++ .../transport/cronet/transport/cronet_api_dummy.c | 85 +++ .../transport/cronet/transport/cronet_transport.c | 640 +++++++++++++++++++++ src/python/grpcio/grpc/_cython/imports.generated.c | 2 + src/python/grpcio/grpc/_cython/imports.generated.h | 4 + src/python/grpcio/grpc_core_dependencies.py | 3 + src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 + src/ruby/ext/grpc/rb_grpc_imports.generated.h | 4 + test/core/surface/public_headers_must_be_c89.c | 1 + third_party/objective_c/Cronet/cronet_c_for_grpc.h | 202 +++++++ tools/doxygen/Doxyfile.core | 1 + tools/doxygen/Doxyfile.core.internal | 40 ++ tools/run_tests/sources_and_headers.json | 120 +++- vsprojects/vcxproj/grpc/grpc.vcxproj | 43 ++ vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 144 +++++ 25 files changed, 1721 insertions(+), 1 deletion(-) create mode 100644 include/grpc/grpc_cronet.h create mode 100644 src/core/ext/transport/cronet/client/secure/cronet_channel_create.c create mode 100644 src/core/ext/transport/cronet/transport/cronet_api_dummy.c create mode 100644 src/core/ext/transport/cronet/transport/cronet_transport.c create mode 100644 third_party/objective_c/Cronet/cronet_c_for_grpc.h (limited to 'src/python/grpcio') diff --git a/BUILD b/BUILD index ad6903d684..1f6fc08cba 100644 --- a/BUILD +++ b/BUILD @@ -285,6 +285,42 @@ cc_library( "src/core/ext/client_config/subchannel_call_holder.h", "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", + "include/grpc/byte_buffer.h", + "include/grpc/grpc.h", + "include/grpc/impl/codegen/alloc.h", + "include/grpc/impl/codegen/atm.h", + "include/grpc/impl/codegen/atm_gcc_atomic.h", + "include/grpc/impl/codegen/atm_gcc_sync.h", + "include/grpc/impl/codegen/atm_win32.h", + "include/grpc/impl/codegen/byte_buffer.h", + "include/grpc/impl/codegen/compression_types.h", + "include/grpc/impl/codegen/connectivity_state.h", + "include/grpc/impl/codegen/grpc_types.h", + "include/grpc/impl/codegen/log.h", + "include/grpc/impl/codegen/port_platform.h", + "include/grpc/impl/codegen/propagation_bits.h", + "include/grpc/impl/codegen/slice.h", + "include/grpc/impl/codegen/slice_buffer.h", + "include/grpc/impl/codegen/status.h", + "include/grpc/impl/codegen/sync.h", + "include/grpc/impl/codegen/sync_generic.h", + "include/grpc/impl/codegen/sync_posix.h", + "include/grpc/impl/codegen/sync_win32.h", + "include/grpc/impl/codegen/time.h", + "include/grpc/status.h", + "include/grpc/support/alloc.h", + "include/grpc/support/atm.h", + "include/grpc/support/host_port.h", + "include/grpc/support/log.h", + "include/grpc/support/port_platform.h", + "include/grpc/support/slice.h", + "include/grpc/support/slice_buffer.h", + "include/grpc/support/string_util.h", + "include/grpc/support/sync.h", + "include/grpc/support/time.h", + "include/grpc/support/useful.h", + "src/core/lib/support/string.h", + "third_party/objective_c/Cronet/cronet_c_for_grpc.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", "src/core/ext/census/aggregation.h", @@ -439,6 +475,9 @@ cc_library( "src/core/ext/client_config/uri_parser.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", + "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", + "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", + "src/core/ext/transport/cronet/transport/cronet_transport.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", @@ -483,6 +522,7 @@ cc_library( "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_win32.h", "include/grpc/impl/codegen/time.h", + "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "include/grpc/census.h", @@ -1460,6 +1500,9 @@ objc_library( "src/core/ext/client_config/uri_parser.c", "src/core/ext/transport/chttp2/server/insecure/server_chttp2.c", "src/core/ext/transport/chttp2/client/insecure/channel_create.c", + "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", + "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", + "src/core/ext/transport/cronet/transport/cronet_transport.c", "src/core/ext/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", "src/core/ext/lb_policy/pick_first/pick_first.c", @@ -1504,6 +1547,7 @@ objc_library( "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_win32.h", "include/grpc/impl/codegen/time.h", + "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "include/grpc/census.h", @@ -1631,6 +1675,42 @@ objc_library( "src/core/ext/client_config/subchannel_call_holder.h", "src/core/ext/client_config/subchannel_index.h", "src/core/ext/client_config/uri_parser.h", + "include/grpc/byte_buffer.h", + "include/grpc/grpc.h", + "include/grpc/impl/codegen/alloc.h", + "include/grpc/impl/codegen/atm.h", + "include/grpc/impl/codegen/atm_gcc_atomic.h", + "include/grpc/impl/codegen/atm_gcc_sync.h", + "include/grpc/impl/codegen/atm_win32.h", + "include/grpc/impl/codegen/byte_buffer.h", + "include/grpc/impl/codegen/compression_types.h", + "include/grpc/impl/codegen/connectivity_state.h", + "include/grpc/impl/codegen/grpc_types.h", + "include/grpc/impl/codegen/log.h", + "include/grpc/impl/codegen/port_platform.h", + "include/grpc/impl/codegen/propagation_bits.h", + "include/grpc/impl/codegen/slice.h", + "include/grpc/impl/codegen/slice_buffer.h", + "include/grpc/impl/codegen/status.h", + "include/grpc/impl/codegen/sync.h", + "include/grpc/impl/codegen/sync_generic.h", + "include/grpc/impl/codegen/sync_posix.h", + "include/grpc/impl/codegen/sync_win32.h", + "include/grpc/impl/codegen/time.h", + "include/grpc/status.h", + "include/grpc/support/alloc.h", + "include/grpc/support/atm.h", + "include/grpc/support/host_port.h", + "include/grpc/support/log.h", + "include/grpc/support/port_platform.h", + "include/grpc/support/slice.h", + "include/grpc/support/slice_buffer.h", + "include/grpc/support/string_util.h", + "include/grpc/support/sync.h", + "include/grpc/support/time.h", + "include/grpc/support/useful.h", + "src/core/lib/support/string.h", + "third_party/objective_c/Cronet/cronet_c_for_grpc.h", "src/core/ext/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", "src/core/ext/census/aggregation.h", diff --git a/Makefile b/Makefile index 1ff2cb67c5..b8925cee47 100644 --- a/Makefile +++ b/Makefile @@ -2634,6 +2634,9 @@ LIBGRPC_SRC = \ src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ + src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ + src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ + src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -2681,6 +2684,7 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ + include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -14348,6 +14352,9 @@ ifneq ($(OPENSSL_DEP),) # otherwise parallel compilation will fail if a source is compiled first. src/core/ext/transport/chttp2/client/secure/secure_channel_create.c: $(OPENSSL_DEP) src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c: $(OPENSSL_DEP) +src/core/ext/transport/cronet/client/secure/cronet_channel_create.c: $(OPENSSL_DEP) +src/core/ext/transport/cronet/transport/cronet_api_dummy.c: $(OPENSSL_DEP) +src/core/ext/transport/cronet/transport/cronet_transport.c: $(OPENSSL_DEP) src/core/lib/http/httpcli_security_connector.c: $(OPENSSL_DEP) src/core/lib/security/b64.c: $(OPENSSL_DEP) src/core/lib/security/client_auth_filter.c: $(OPENSSL_DEP) diff --git a/binding.gyp b/binding.gyp index 8bc2aee3d1..0d69fc5826 100644 --- a/binding.gyp +++ b/binding.gyp @@ -709,6 +709,9 @@ 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', + 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', + 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', + 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/build.yaml b/build.yaml index b2cbd4d890..aeb31003e7 100644 --- a/build.yaml +++ b/build.yaml @@ -400,6 +400,7 @@ filegroups: - grpc_client_config - name: grpc_secure public_headers: + - include/grpc/grpc_cronet.h - include/grpc/grpc_security.h - include/grpc/grpc_security_constants.h headers: @@ -547,6 +548,63 @@ filegroups: - grpc_transport_chttp2 - grpc_base - grpc_secure +- name: grpc_transport_cronet_client_secure + headers: + - include/grpc/byte_buffer.h + - include/grpc/grpc.h + - include/grpc/impl/codegen/alloc.h + - include/grpc/impl/codegen/atm.h + - include/grpc/impl/codegen/atm_gcc_atomic.h + - include/grpc/impl/codegen/atm_gcc_sync.h + - include/grpc/impl/codegen/atm_win32.h + - include/grpc/impl/codegen/byte_buffer.h + - include/grpc/impl/codegen/compression_types.h + - include/grpc/impl/codegen/connectivity_state.h + - include/grpc/impl/codegen/grpc_types.h + - include/grpc/impl/codegen/log.h + - include/grpc/impl/codegen/port_platform.h + - include/grpc/impl/codegen/propagation_bits.h + - include/grpc/impl/codegen/slice.h + - include/grpc/impl/codegen/slice_buffer.h + - include/grpc/impl/codegen/status.h + - include/grpc/impl/codegen/sync.h + - include/grpc/impl/codegen/sync_generic.h + - include/grpc/impl/codegen/sync_posix.h + - include/grpc/impl/codegen/sync_win32.h + - include/grpc/impl/codegen/time.h + - include/grpc/status.h + - include/grpc/support/alloc.h + - include/grpc/support/atm.h + - include/grpc/support/host_port.h + - include/grpc/support/log.h + - include/grpc/support/port_platform.h + - include/grpc/support/slice.h + - include/grpc/support/slice_buffer.h + - include/grpc/support/string_util.h + - include/grpc/support/sync.h + - include/grpc/support/time.h + - include/grpc/support/useful.h + - src/core/ext/transport/chttp2/transport/incoming_metadata.h + - src/core/lib/channel/channel_stack.h + - src/core/lib/channel/context.h + - src/core/lib/debug/trace.h + - src/core/lib/iomgr/closure.h + - src/core/lib/iomgr/exec_ctx.h + - src/core/lib/iomgr/pollset.h + - src/core/lib/iomgr/pollset_set.h + - src/core/lib/support/string.h + - src/core/lib/surface/channel.h + - src/core/lib/surface/channel_stack_type.h + - src/core/lib/transport/byte_stream.h + - src/core/lib/transport/metadata.h + - src/core/lib/transport/metadata_batch.h + - src/core/lib/transport/transport.h + - src/core/lib/transport/transport_impl.h + - third_party/objective_c/Cronet/cronet_c_for_grpc.h + src: + - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c + - src/core/ext/transport/cronet/transport/cronet_api_dummy.c + - src/core/ext/transport/cronet/transport/cronet_transport.c - name: nanopb headers: - third_party/nanopb/pb.h @@ -734,6 +792,7 @@ libs: - grpc_transport_chttp2_client_secure - grpc_transport_chttp2_server_insecure - grpc_transport_chttp2_client_insecure + - grpc_transport_cronet_client_secure - grpc_lb_policy_grpclb - grpc_lb_policy_pick_first - grpc_lb_policy_round_robin diff --git a/config.m4 b/config.m4 index c8d2aae106..58c3d82736 100644 --- a/config.m4 +++ b/config.m4 @@ -228,6 +228,9 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ + src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ + src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ + src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -566,6 +569,8 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/insecure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/secure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/cronet/client/secure) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/cronet/transport) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/channel) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug) diff --git a/gRPC.podspec b/gRPC.podspec index 393733209d..1a0ddc0d55 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -288,6 +288,42 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_call_holder.h', 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', + 'include/grpc/byte_buffer.h', + 'include/grpc/grpc.h', + 'include/grpc/impl/codegen/alloc.h', + 'include/grpc/impl/codegen/atm.h', + 'include/grpc/impl/codegen/atm_gcc_atomic.h', + 'include/grpc/impl/codegen/atm_gcc_sync.h', + 'include/grpc/impl/codegen/atm_win32.h', + 'include/grpc/impl/codegen/byte_buffer.h', + 'include/grpc/impl/codegen/compression_types.h', + 'include/grpc/impl/codegen/connectivity_state.h', + 'include/grpc/impl/codegen/grpc_types.h', + 'include/grpc/impl/codegen/log.h', + 'include/grpc/impl/codegen/port_platform.h', + 'include/grpc/impl/codegen/propagation_bits.h', + 'include/grpc/impl/codegen/slice.h', + 'include/grpc/impl/codegen/slice_buffer.h', + 'include/grpc/impl/codegen/status.h', + 'include/grpc/impl/codegen/sync.h', + 'include/grpc/impl/codegen/sync_generic.h', + 'include/grpc/impl/codegen/sync_posix.h', + 'include/grpc/impl/codegen/sync_win32.h', + 'include/grpc/impl/codegen/time.h', + 'include/grpc/status.h', + 'include/grpc/support/alloc.h', + 'include/grpc/support/atm.h', + 'include/grpc/support/host_port.h', + 'include/grpc/support/log.h', + 'include/grpc/support/port_platform.h', + 'include/grpc/support/slice.h', + 'include/grpc/support/slice_buffer.h', + 'include/grpc/support/string_util.h', + 'include/grpc/support/sync.h', + 'include/grpc/support/time.h', + 'include/grpc/support/useful.h', + 'src/core/lib/support/string.h', + 'third_party/objective_c/Cronet/cronet_c_for_grpc.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', @@ -326,6 +362,7 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/sync_posix.h', 'include/grpc/impl/codegen/sync_win32.h', 'include/grpc/impl/codegen/time.h', + 'include/grpc/grpc_cronet.h', 'include/grpc/grpc_security.h', 'include/grpc/grpc_security_constants.h', 'include/grpc/census.h', @@ -475,6 +512,9 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', + 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', + 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', + 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', @@ -631,6 +671,42 @@ Pod::Spec.new do |s| 'src/core/ext/client_config/subchannel_call_holder.h', 'src/core/ext/client_config/subchannel_index.h', 'src/core/ext/client_config/uri_parser.h', + 'include/grpc/byte_buffer.h', + 'include/grpc/grpc.h', + 'include/grpc/impl/codegen/alloc.h', + 'include/grpc/impl/codegen/atm.h', + 'include/grpc/impl/codegen/atm_gcc_atomic.h', + 'include/grpc/impl/codegen/atm_gcc_sync.h', + 'include/grpc/impl/codegen/atm_win32.h', + 'include/grpc/impl/codegen/byte_buffer.h', + 'include/grpc/impl/codegen/compression_types.h', + 'include/grpc/impl/codegen/connectivity_state.h', + 'include/grpc/impl/codegen/grpc_types.h', + 'include/grpc/impl/codegen/log.h', + 'include/grpc/impl/codegen/port_platform.h', + 'include/grpc/impl/codegen/propagation_bits.h', + 'include/grpc/impl/codegen/slice.h', + 'include/grpc/impl/codegen/slice_buffer.h', + 'include/grpc/impl/codegen/status.h', + 'include/grpc/impl/codegen/sync.h', + 'include/grpc/impl/codegen/sync_generic.h', + 'include/grpc/impl/codegen/sync_posix.h', + 'include/grpc/impl/codegen/sync_win32.h', + 'include/grpc/impl/codegen/time.h', + 'include/grpc/status.h', + 'include/grpc/support/alloc.h', + 'include/grpc/support/atm.h', + 'include/grpc/support/host_port.h', + 'include/grpc/support/log.h', + 'include/grpc/support/port_platform.h', + 'include/grpc/support/slice.h', + 'include/grpc/support/slice_buffer.h', + 'include/grpc/support/string_util.h', + 'include/grpc/support/sync.h', + 'include/grpc/support/time.h', + 'include/grpc/support/useful.h', + 'src/core/lib/support/string.h', + 'third_party/objective_c/Cronet/cronet_c_for_grpc.h', 'src/core/ext/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', diff --git a/grpc.def b/grpc.def index 61948ed1b8..09a94a6cd0 100644 --- a/grpc.def +++ b/grpc.def @@ -87,6 +87,7 @@ EXPORTS grpc_header_nonbin_value_is_legal grpc_is_binary_header grpc_call_error_to_string + grpc_cronet_secure_channel_create grpc_auth_property_iterator_next grpc_auth_context_property_iterator grpc_auth_context_peer_identity diff --git a/grpc.gemspec b/grpc.gemspec index 240ea1ca1f..2d5045faba 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -169,6 +169,7 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/sync_posix.h ) s.files += %w( include/grpc/impl/codegen/sync_win32.h ) s.files += %w( include/grpc/impl/codegen/time.h ) + s.files += %w( include/grpc/grpc_cronet.h ) s.files += %w( include/grpc/grpc_security.h ) s.files += %w( include/grpc/grpc_security_constants.h ) s.files += %w( include/grpc/census.h ) @@ -296,6 +297,42 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_config/subchannel_call_holder.h ) s.files += %w( src/core/ext/client_config/subchannel_index.h ) s.files += %w( src/core/ext/client_config/uri_parser.h ) + s.files += %w( include/grpc/byte_buffer.h ) + s.files += %w( include/grpc/grpc.h ) + s.files += %w( include/grpc/impl/codegen/alloc.h ) + s.files += %w( include/grpc/impl/codegen/atm.h ) + s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) + s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) + s.files += %w( include/grpc/impl/codegen/atm_win32.h ) + s.files += %w( include/grpc/impl/codegen/byte_buffer.h ) + s.files += %w( include/grpc/impl/codegen/compression_types.h ) + s.files += %w( include/grpc/impl/codegen/connectivity_state.h ) + s.files += %w( include/grpc/impl/codegen/grpc_types.h ) + s.files += %w( include/grpc/impl/codegen/log.h ) + s.files += %w( include/grpc/impl/codegen/port_platform.h ) + s.files += %w( include/grpc/impl/codegen/propagation_bits.h ) + s.files += %w( include/grpc/impl/codegen/slice.h ) + s.files += %w( include/grpc/impl/codegen/slice_buffer.h ) + s.files += %w( include/grpc/impl/codegen/status.h ) + s.files += %w( include/grpc/impl/codegen/sync.h ) + s.files += %w( include/grpc/impl/codegen/sync_generic.h ) + s.files += %w( include/grpc/impl/codegen/sync_posix.h ) + s.files += %w( include/grpc/impl/codegen/sync_win32.h ) + s.files += %w( include/grpc/impl/codegen/time.h ) + s.files += %w( include/grpc/status.h ) + s.files += %w( include/grpc/support/alloc.h ) + s.files += %w( include/grpc/support/atm.h ) + s.files += %w( include/grpc/support/host_port.h ) + s.files += %w( include/grpc/support/log.h ) + s.files += %w( include/grpc/support/port_platform.h ) + s.files += %w( include/grpc/support/slice.h ) + s.files += %w( include/grpc/support/slice_buffer.h ) + s.files += %w( include/grpc/support/string_util.h ) + s.files += %w( include/grpc/support/sync.h ) + s.files += %w( include/grpc/support/time.h ) + s.files += %w( include/grpc/support/useful.h ) + s.files += %w( src/core/lib/support/string.h ) + s.files += %w( third_party/objective_c/Cronet/cronet_c_for_grpc.h ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.h ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h ) s.files += %w( third_party/nanopb/pb.h ) @@ -454,6 +491,9 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/client_config/uri_parser.c ) s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) + s.files += %w( src/core/ext/transport/cronet/client/secure/cronet_channel_create.c ) + s.files += %w( src/core/ext/transport/cronet/transport/cronet_api_dummy.c ) + s.files += %w( src/core/ext/transport/cronet/transport/cronet_transport.c ) s.files += %w( src/core/ext/lb_policy/grpclb/load_balancer_api.c ) s.files += %w( src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c ) s.files += %w( third_party/nanopb/pb_common.c ) diff --git a/include/grpc/grpc_cronet.h b/include/grpc/grpc_cronet.h new file mode 100644 index 0000000000..295e0f55e8 --- /dev/null +++ b/include/grpc/grpc_cronet.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_GRPC_CRONET_H +#define GRPC_GRPC_CRONET_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( + void *engine, const char *target, const grpc_channel_args *args, + void *reserved); + +#ifdef __cplusplus +} +#endif + +#endif /* GRPC_GRPC_CRONET_H */ diff --git a/package.xml b/package.xml index 4c159e6024..cf11ea8f07 100644 --- a/package.xml +++ b/package.xml @@ -176,6 +176,7 @@ + @@ -303,6 +304,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -461,6 +498,9 @@ + + + diff --git a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c new file mode 100644 index 0000000000..df1acddcc0 --- /dev/null +++ b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c @@ -0,0 +1,69 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include +#include + +#include +#include + +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/transport/transport_impl.h" + +// Cronet transport object +typedef struct cronet_transport { + grpc_transport base; // must be first element in this structure + void *engine; + char *host; +} cronet_transport; + +extern grpc_transport_vtable grpc_cronet_vtable; + +GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( + void *engine, const char *target, const grpc_channel_args *args, + void *reserved) { + cronet_transport *ct = gpr_malloc(sizeof(cronet_transport)); + ct->base.vtable = &grpc_cronet_vtable; + ct->engine = engine; + ct->host = gpr_malloc(strlen(target) + 1); + strcpy(ct->host, target); + gpr_log(GPR_DEBUG, + "grpc_create_cronet_transport: cronet_engine = %p, target=%s", engine, + ct->host); + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + return grpc_channel_create(&exec_ctx, target, args, + GRPC_CLIENT_DIRECT_CHANNEL, (grpc_transport *)ct); +} diff --git a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c new file mode 100644 index 0000000000..687026c9fd --- /dev/null +++ b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c @@ -0,0 +1,85 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* This file has empty implementation of all the functions exposed by the cronet +library, so we can build it in all environments */ + +#include + +#include + +#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h" + +#ifdef GRPC_COMPILE_WITH_CRONET +/* link with the real CRONET library in the build system */ +#else +/* Dummy implementation of cronet API just to test for build-ability */ +cronet_bidirectional_stream* cronet_bidirectional_stream_create( + cronet_engine* engine, void* annotation, + cronet_bidirectional_stream_callback* callback) { + GPR_ASSERT(0); + return NULL; +} + +int cronet_bidirectional_stream_destroy(cronet_bidirectional_stream* stream) { + GPR_ASSERT(0); + return 0; +} + +int cronet_bidirectional_stream_start( + cronet_bidirectional_stream* stream, const char* url, int priority, + const char* method, const cronet_bidirectional_stream_header_array* headers, + bool end_of_stream) { + GPR_ASSERT(0); + return 0; +} + +int cronet_bidirectional_stream_read(cronet_bidirectional_stream* stream, + char* buffer, int capacity) { + GPR_ASSERT(0); + return 0; +} + +int cronet_bidirectional_stream_write(cronet_bidirectional_stream* stream, + const char* buffer, int count, + bool end_of_stream) { + GPR_ASSERT(0); + return 0; +} + +int cronet_bidirectional_stream_cancel(cronet_bidirectional_stream* stream) { + GPR_ASSERT(0); + return 0; +} + +#endif /* GRPC_COMPILE_WITH_CRONET */ diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c new file mode 100644 index 0000000000..5bb085195c --- /dev/null +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -0,0 +1,640 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/support/string.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/transport/metadata_batch.h" +#include "src/core/lib/transport/transport_impl.h" +#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h" + +#define GRPC_HEADER_SIZE_IN_BYTES 5 + +// Global flag that gets set with GRPC_TRACE env variable +int grpc_cronet_trace = 1; + +// Cronet transport object +struct grpc_cronet_transport { + grpc_transport base; /* must be first element in this structure */ + cronet_engine *engine; + char *host; +}; + +typedef struct grpc_cronet_transport grpc_cronet_transport; + +enum send_state { + CRONET_SEND_IDLE = 0, + CRONET_REQ_STARTED, + CRONET_SEND_HEADER, + CRONET_WRITE, + CRONET_WRITE_COMPLETED, +}; + +enum recv_state { + CRONET_RECV_IDLE = 0, + CRONET_RECV_READ_LENGTH, + CRONET_RECV_READ_DATA, + CRONET_RECV_CLOSED, +}; + +static const char *recv_state_name[] = { + "CRONET_RECV_IDLE", "CRONET_RECV_READ_LENGTH", "CRONET_RECV_READ_DATA,", + "CRONET_RECV_CLOSED"}; + +// Enum that identifies calling function. +enum e_caller { + PERFORM_STREAM_OP, + ON_READ_COMPLETE, + ON_RESPONSE_HEADERS_RECEIVED, + ON_RESPONSE_TRAILERS_RECEIVED +}; + +enum callback_id { + CB_SEND_INITIAL_METADATA = 0, + CB_SEND_MESSAGE, + CB_SEND_TRAILING_METADATA, + CB_RECV_MESSAGE, + CB_RECV_INITIAL_METADATA, + CB_RECV_TRAILING_METADATA, + CB_NUM_CALLBACKS +}; + +struct stream_obj { + // we store received bytes here as they trickle in. + gpr_slice_buffer write_slice_buffer; + cronet_bidirectional_stream *cbs; + gpr_slice slice; + gpr_slice_buffer read_slice_buffer; + struct grpc_slice_buffer_stream sbs; + char *read_buffer; + int remaining_read_bytes; + int total_read_bytes; + + char *write_buffer; + size_t write_buffer_size; + + // Hold the URL + char *url; + + bool response_headers_received; + bool read_requested; + bool response_trailers_received; + bool read_closed; + + // Recv message stuff + grpc_byte_buffer **recv_message; + // Initial metadata stuff + grpc_metadata_batch *recv_initial_metadata; + // Trailing metadata stuff + grpc_metadata_batch *recv_trailing_metadata; + grpc_chttp2_incoming_metadata_buffer imb; + + // This mutex protects receive state machine execution + gpr_mu recv_mu; + // we can queue up up to 2 callbacks for each OP + grpc_closure *callback_list[CB_NUM_CALLBACKS][2]; + + // storage for header + cronet_bidirectional_stream_header *headers; + uint32_t num_headers; + cronet_bidirectional_stream_header_array header_array; + // state tracking + enum recv_state cronet_recv_state; + enum send_state cronet_send_state; +}; + +typedef struct stream_obj stream_obj; + +static void next_send_step(stream_obj *s); +static void next_recv_step(stream_obj *s, enum e_caller caller); + +static void set_pollset_do_nothing(grpc_exec_ctx *exec_ctx, grpc_transport *gt, + grpc_stream *gs, grpc_pollset *pollset) {} + +static void enqueue_callbacks(grpc_closure *callback_list[]) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + if (callback_list[0]) { + grpc_exec_ctx_enqueue(&exec_ctx, callback_list[0], true, NULL); + callback_list[0] = NULL; + } + if (callback_list[1]) { + grpc_exec_ctx_enqueue(&exec_ctx, callback_list[1], true, NULL); + callback_list[1] = NULL; + } + grpc_exec_ctx_finish(&exec_ctx); +} + +static void on_canceled(cronet_bidirectional_stream *stream) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "on_canceled %p", stream); + } +} + +static void on_failed(cronet_bidirectional_stream *stream, int net_error) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "on_failed %p, error = %d", stream, net_error); + } +} + +static void on_succeeded(cronet_bidirectional_stream *stream) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "on_succeeded %p", stream); + } +} + +static void on_response_trailers_received( + cronet_bidirectional_stream *stream, + const cronet_bidirectional_stream_header_array *trailers) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "R: on_response_trailers_received"); + } + stream_obj *s = (stream_obj *)stream->annotation; + + memset(&s->imb, 0, sizeof(s->imb)); + grpc_chttp2_incoming_metadata_buffer_init(&s->imb); + unsigned int i = 0; + for (i = 0; i < trailers->count; i++) { + grpc_chttp2_incoming_metadata_buffer_add( + &s->imb, grpc_mdelem_from_metadata_strings( + grpc_mdstr_from_string(trailers->headers[i].key), + grpc_mdstr_from_string(trailers->headers[i].value))); + } + s->response_trailers_received = true; + next_recv_step(s, ON_RESPONSE_TRAILERS_RECEIVED); +} + +static void on_write_completed(cronet_bidirectional_stream *stream, + const char *data) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "W: on_write_completed"); + } + stream_obj *s = (stream_obj *)stream->annotation; + enqueue_callbacks(s->callback_list[CB_SEND_MESSAGE]); + s->cronet_send_state = CRONET_WRITE_COMPLETED; + next_send_step(s); +} + +static void process_recv_message(stream_obj *s, const uint8_t *recv_data) { + gpr_slice read_data_slice = gpr_slice_malloc((uint32_t)s->total_read_bytes); + uint8_t *dst_p = GPR_SLICE_START_PTR(read_data_slice); + memcpy(dst_p, recv_data, (size_t)s->total_read_bytes); + gpr_slice_buffer_add(&s->read_slice_buffer, read_data_slice); + grpc_slice_buffer_stream_init(&s->sbs, &s->read_slice_buffer, 0); + *s->recv_message = (grpc_byte_buffer *)&s->sbs; +} + +static int parse_grpc_header(const uint8_t *data) { + const uint8_t *p = data + 1; + int length = 0; + length |= ((uint8_t)*p++) << 24; + length |= ((uint8_t)*p++) << 16; + length |= ((uint8_t)*p++) << 8; + length |= ((uint8_t)*p++); + return length; +} + +static void on_read_completed(cronet_bidirectional_stream *stream, char *data, + int count) { + stream_obj *s = (stream_obj *)stream->annotation; + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "R: on_read_completed count=%d, total=%d, remaining=%d", + count, s->total_read_bytes, s->remaining_read_bytes); + } + if (count > 0) { + GPR_ASSERT(s->recv_message); + s->remaining_read_bytes -= count; + next_recv_step(s, ON_READ_COMPLETE); + } else { + s->read_closed = true; + next_recv_step(s, ON_READ_COMPLETE); + } +} + +static void on_response_headers_received( + cronet_bidirectional_stream *stream, + const cronet_bidirectional_stream_header_array *headers, + const char *negotiated_protocol) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "R: on_response_headers_received"); + } + stream_obj *s = (stream_obj *)stream->annotation; + enqueue_callbacks(s->callback_list[CB_RECV_INITIAL_METADATA]); + s->response_headers_received = true; + next_recv_step(s, ON_RESPONSE_HEADERS_RECEIVED); +} + +static void on_request_headers_sent(cronet_bidirectional_stream *stream) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "W: on_request_headers_sent"); + } + stream_obj *s = (stream_obj *)stream->annotation; + enqueue_callbacks(s->callback_list[CB_SEND_INITIAL_METADATA]); + s->cronet_send_state = CRONET_SEND_HEADER; + next_send_step(s); +} + +// Callback function pointers (invoked by cronet in response to events) +static cronet_bidirectional_stream_callback callbacks = { + on_request_headers_sent, + on_response_headers_received, + on_read_completed, + on_write_completed, + on_response_trailers_received, + on_succeeded, + on_failed, + on_canceled}; + +static void invoke_closing_callback(stream_obj *s) { + grpc_chttp2_incoming_metadata_buffer_publish(&s->imb, + s->recv_trailing_metadata); + if (s->callback_list[CB_RECV_TRAILING_METADATA]) { + enqueue_callbacks(s->callback_list[CB_RECV_TRAILING_METADATA]); + } +} + +static void set_recv_state(stream_obj *s, enum recv_state state) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "next_state = %s", recv_state_name[state]); + } + s->cronet_recv_state = state; +} + +// This is invoked from perform_stream_op, and all on_xxxx callbacks. +static void next_recv_step(stream_obj *s, enum e_caller caller) { + gpr_mu_lock(&s->recv_mu); + switch (s->cronet_recv_state) { + case CRONET_RECV_IDLE: + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_IDLE"); + } + if (caller == PERFORM_STREAM_OP || + caller == ON_RESPONSE_HEADERS_RECEIVED) { + if (s->read_closed && s->response_trailers_received) { + invoke_closing_callback(s); + set_recv_state(s, CRONET_RECV_CLOSED); + } else if (s->response_headers_received == true && + s->read_requested == true) { + set_recv_state(s, CRONET_RECV_READ_LENGTH); + s->total_read_bytes = s->remaining_read_bytes = + GRPC_HEADER_SIZE_IN_BYTES; + GPR_ASSERT(s->read_buffer); + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()"); + } + cronet_bidirectional_stream_read(s->cbs, s->read_buffer, + s->remaining_read_bytes); + } + } + break; + case CRONET_RECV_READ_LENGTH: + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_LENGTH"); + } + if (caller == ON_READ_COMPLETE) { + if (s->read_closed) { + invoke_closing_callback(s); + enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]); + set_recv_state(s, CRONET_RECV_CLOSED); + } else { + GPR_ASSERT(s->remaining_read_bytes == 0); + set_recv_state(s, CRONET_RECV_READ_DATA); + s->total_read_bytes = s->remaining_read_bytes = + parse_grpc_header((const uint8_t *)s->read_buffer); + s->read_buffer = + gpr_realloc(s->read_buffer, (uint32_t)s->remaining_read_bytes); + GPR_ASSERT(s->read_buffer); + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()"); + } + cronet_bidirectional_stream_read(s->cbs, (char *)s->read_buffer, + s->remaining_read_bytes); + } + } + break; + case CRONET_RECV_READ_DATA: + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_DATA"); + } + if (caller == ON_READ_COMPLETE) { + if (s->remaining_read_bytes > 0) { + int offset = s->total_read_bytes - s->remaining_read_bytes; + GPR_ASSERT(s->read_buffer); + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()"); + } + cronet_bidirectional_stream_read( + s->cbs, (char *)s->read_buffer + offset, s->remaining_read_bytes); + } else { + gpr_slice_buffer_init(&s->read_slice_buffer); + uint8_t *p = (uint8_t *)s->read_buffer; + process_recv_message(s, p); + set_recv_state(s, CRONET_RECV_IDLE); + enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]); + } + } + break; + case CRONET_RECV_CLOSED: + break; + default: + GPR_ASSERT(0); // Should not reach here + break; + } + gpr_mu_unlock(&s->recv_mu); +} + +// This function takes the data from s->write_slice_buffer and assembles into +// a contiguous byte stream with 5 byte gRPC header prepended. +static void create_grpc_frame(stream_obj *s) { + gpr_slice slice = gpr_slice_buffer_take_first(&s->write_slice_buffer); + uint8_t *raw_data = GPR_SLICE_START_PTR(slice); + size_t length = GPR_SLICE_LENGTH(slice); + s->write_buffer_size = length + GRPC_HEADER_SIZE_IN_BYTES; + s->write_buffer = gpr_realloc(s->write_buffer, s->write_buffer_size); + uint8_t *p = (uint8_t *)s->write_buffer; + // Append 5 byte header + *p++ = 0; + *p++ = (uint8_t)(length >> 24); + *p++ = (uint8_t)(length >> 16); + *p++ = (uint8_t)(length >> 8); + *p++ = (uint8_t)(length); + // append actual data + memcpy(p, raw_data, length); +} + +static void do_write(stream_obj *s) { + gpr_slice_buffer *sb = &s->write_slice_buffer; + GPR_ASSERT(sb->count <= 1); + if (sb->count > 0) { + create_grpc_frame(s); + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write"); + } + cronet_bidirectional_stream_write(s->cbs, s->write_buffer, + (int)s->write_buffer_size, false); + } +} + +// +static void next_send_step(stream_obj *s) { + switch (s->cronet_send_state) { + case CRONET_SEND_IDLE: + GPR_ASSERT( + s->cbs); // cronet_bidirectional_stream is not initialized yet. + s->cronet_send_state = CRONET_REQ_STARTED; + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_start to %s", s->url); + } + cronet_bidirectional_stream_start(s->cbs, s->url, 0, "POST", + &s->header_array, false); + // we no longer need the memory that was allocated earlier. + gpr_free(s->header_array.headers); + break; + case CRONET_SEND_HEADER: + do_write(s); + s->cronet_send_state = CRONET_WRITE; + break; + case CRONET_WRITE_COMPLETED: + do_write(s); + break; + default: + GPR_ASSERT(0); + break; + } +} + +static void convert_metadata_to_cronet_headers(grpc_linked_mdelem *head, + const char *host, + stream_obj *s) { + grpc_linked_mdelem *curr = head; + // Walk the linked list and get number of header fields + uint32_t num_headers_available = 0; + while (curr != NULL) { + curr = curr->next; + num_headers_available++; + } + // Allocate enough memory + s->headers = (cronet_bidirectional_stream_header *)gpr_malloc( + sizeof(cronet_bidirectional_stream_header) * num_headers_available); + + // Walk the linked list again, this time copying the header fields. + // s->num_headers + // can be less than num_headers_available, as some headers are not used for + // cronet + curr = head; + s->num_headers = 0; + while (s->num_headers < num_headers_available) { + grpc_mdelem *mdelem = curr->md; + curr = curr->next; + const char *key = grpc_mdstr_as_c_string(mdelem->key); + const char *value = grpc_mdstr_as_c_string(mdelem->value); + if (strcmp(key, ":scheme") == 0 || strcmp(key, ":method") == 0 || + strcmp(key, ":authority") == 0) { + // Cronet populates these fields on its own. + continue; + } + if (strcmp(key, ":path") == 0) { + // Create URL by appending :path value to the hostname + gpr_asprintf(&s->url, "https://%s%s", host, value); + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "extracted URL = %s", s->url); + } + continue; + } + s->headers[s->num_headers].key = key; + s->headers[s->num_headers].value = value; + s->num_headers++; + if (curr == NULL) { + break; + } + } +} + +static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, + grpc_stream *gs, grpc_transport_stream_op *op) { + grpc_cronet_transport *ct = (grpc_cronet_transport *)gt; + GPR_ASSERT(ct->engine); + stream_obj *s = (stream_obj *)gs; + if (op->recv_trailing_metadata) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, + "perform_stream_op - recv_trailing_metadata: on_complete=%p", + op->on_complete); + } + s->recv_trailing_metadata = op->recv_trailing_metadata; + GPR_ASSERT(!s->callback_list[CB_RECV_TRAILING_METADATA][0]); + s->callback_list[CB_RECV_TRAILING_METADATA][0] = op->on_complete; + } + if (op->recv_message) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "perform_stream_op - recv_message: on_complete=%p", + op->on_complete); + } + s->recv_message = (grpc_byte_buffer **)op->recv_message; + GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][0]); + GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][1]); + s->callback_list[CB_RECV_MESSAGE][0] = op->recv_message_ready; + s->callback_list[CB_RECV_MESSAGE][1] = op->on_complete; + s->read_requested = true; + next_recv_step(s, PERFORM_STREAM_OP); + } + if (op->recv_initial_metadata) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "perform_stream_op - recv_initial_metadata:=%p", + op->on_complete); + } + s->recv_initial_metadata = op->recv_initial_metadata; + GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][0]); + GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][1]); + s->callback_list[CB_RECV_INITIAL_METADATA][0] = + op->recv_initial_metadata_ready; + s->callback_list[CB_RECV_INITIAL_METADATA][1] = op->on_complete; + } + if (op->send_initial_metadata) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, + "perform_stream_op - send_initial_metadata: on_complete=%p", + op->on_complete); + } + s->num_headers = 0; + convert_metadata_to_cronet_headers(op->send_initial_metadata->list.head, + ct->host, s); + s->header_array.count = s->num_headers; + s->header_array.capacity = s->num_headers; + s->header_array.headers = s->headers; + GPR_ASSERT(!s->callback_list[CB_SEND_INITIAL_METADATA][0]); + s->callback_list[CB_SEND_INITIAL_METADATA][0] = op->on_complete; + } + if (op->send_message) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "perform_stream_op - send_message: on_complete=%p", + op->on_complete); + } + grpc_byte_stream_next(exec_ctx, op->send_message, &s->slice, + op->send_message->length, NULL); + // Check that compression flag is not ON. We don't support compression yet. + // TODO (makdharma): add compression support + GPR_ASSERT(op->send_message->flags == 0); + gpr_slice_buffer_add(&s->write_slice_buffer, s->slice); + if (s->cbs == NULL) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_create"); + } + s->cbs = cronet_bidirectional_stream_create(ct->engine, s, &callbacks); + GPR_ASSERT(s->cbs); + s->read_closed = false; + s->response_trailers_received = false; + s->response_headers_received = false; + s->cronet_send_state = CRONET_SEND_IDLE; + s->cronet_recv_state = CRONET_RECV_IDLE; + } + GPR_ASSERT(!s->callback_list[CB_SEND_MESSAGE][0]); + s->callback_list[CB_SEND_MESSAGE][0] = op->on_complete; + next_send_step(s); + } + if (op->send_trailing_metadata) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, + "perform_stream_op - send_trailing_metadata: on_complete=%p", + op->on_complete); + } + GPR_ASSERT(!s->callback_list[CB_SEND_TRAILING_METADATA][0]); + s->callback_list[CB_SEND_TRAILING_METADATA][0] = op->on_complete; + if (s->cbs) { + // Send an "empty" write to the far end to signal that we're done. + // This will induce the server to send down trailers. + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write"); + } + cronet_bidirectional_stream_write(s->cbs, "abc", 0, true); + } else { + // We never created a stream. This was probably an empty request. + invoke_closing_callback(s); + } + } +} + +static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, + grpc_stream *gs, grpc_stream_refcount *refcount, + const void *server_data) { + stream_obj *s = (stream_obj *)gs; + memset(s->callback_list, 0, sizeof(s->callback_list)); + s->cbs = NULL; + gpr_mu_init(&s->recv_mu); + s->read_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES); + s->write_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES); + gpr_slice_buffer_init(&s->write_slice_buffer); + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "cronet_transport - init_stream"); + } + return 0; +} + +static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, + grpc_stream *gs, void *and_free_memory) { + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "Destroy stream"); + } + stream_obj *s = (stream_obj *)gs; + s->cbs = NULL; + gpr_free(s->read_buffer); + gpr_free(s->write_buffer); + gpr_free(s->url); + gpr_mu_destroy(&s->recv_mu); + if (and_free_memory) { + gpr_free(and_free_memory); + } +} + +static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { + grpc_cronet_transport *ct = (grpc_cronet_transport *)gt; + gpr_free(ct->host); + if (grpc_cronet_trace) { + gpr_log(GPR_DEBUG, "Destroy transport"); + } +} + +const grpc_transport_vtable grpc_cronet_vtable = { + sizeof(stream_obj), "cronet_http", init_stream, + set_pollset_do_nothing, perform_stream_op, NULL, + destroy_stream, destroy_transport, NULL}; diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c index f0a40dbb35..09551472b5 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.c +++ b/src/python/grpcio/grpc/_cython/imports.generated.c @@ -125,6 +125,7 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; +grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -395,6 +396,7 @@ void pygrpc_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); + grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h index d5e810b7cf..54c8aaad13 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/python/grpcio/grpc/_cython/imports.generated.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,9 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import +typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); +extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; +#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 4b98dc1a13..c6af69360d 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -222,6 +222,9 @@ CORE_SOURCE_FILES = [ 'src/core/ext/client_config/uri_parser.c', 'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', + 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c', + 'src/core/ext/transport/cronet/transport/cronet_api_dummy.c', + 'src/core/ext/transport/cronet/transport/cronet_transport.c', 'src/core/ext/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index bc43f9d36b..cebbe8c40f 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -125,6 +125,7 @@ grpc_header_key_is_legal_type grpc_header_key_is_legal_import; grpc_header_nonbin_value_is_legal_type grpc_header_nonbin_value_is_legal_import; grpc_is_binary_header_type grpc_is_binary_header_import; grpc_call_error_to_string_type grpc_call_error_to_string_import; +grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; grpc_auth_context_property_iterator_type grpc_auth_context_property_iterator_import; grpc_auth_context_peer_identity_type grpc_auth_context_peer_identity_import; @@ -391,6 +392,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_header_nonbin_value_is_legal_import = (grpc_header_nonbin_value_is_legal_type) GetProcAddress(library, "grpc_header_nonbin_value_is_legal"); grpc_is_binary_header_import = (grpc_is_binary_header_type) GetProcAddress(library, "grpc_is_binary_header"); grpc_call_error_to_string_import = (grpc_call_error_to_string_type) GetProcAddress(library, "grpc_call_error_to_string"); + grpc_cronet_secure_channel_create_import = (grpc_cronet_secure_channel_create_type) GetProcAddress(library, "grpc_cronet_secure_channel_create"); grpc_auth_property_iterator_next_import = (grpc_auth_property_iterator_next_type) GetProcAddress(library, "grpc_auth_property_iterator_next"); grpc_auth_context_property_iterator_import = (grpc_auth_context_property_iterator_type) GetProcAddress(library, "grpc_auth_context_property_iterator"); grpc_auth_context_peer_identity_import = (grpc_auth_context_peer_identity_type) GetProcAddress(library, "grpc_auth_context_peer_identity"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index b67361ca25..d7ea6c574c 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,9 @@ extern grpc_is_binary_header_type grpc_is_binary_header_import; typedef const char *(*grpc_call_error_to_string_type)(grpc_call_error error); extern grpc_call_error_to_string_type grpc_call_error_to_string_import; #define grpc_call_error_to_string grpc_call_error_to_string_import +typedef grpc_channel *(*grpc_cronet_secure_channel_create_type)(void *engine, const char *target, const grpc_channel_args *args, void *reserved); +extern grpc_cronet_secure_channel_create_type grpc_cronet_secure_channel_create_import; +#define grpc_cronet_secure_channel_create grpc_cronet_secure_channel_create_import typedef const grpc_auth_property *(*grpc_auth_property_iterator_next_type)(grpc_auth_property_iterator *it); extern grpc_auth_property_iterator_next_type grpc_auth_property_iterator_next_import; #define grpc_auth_property_iterator_next grpc_auth_property_iterator_next_import diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 3eeb55d033..fd6ff2c26f 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/third_party/objective_c/Cronet/cronet_c_for_grpc.h b/third_party/objective_c/Cronet/cronet_c_for_grpc.h new file mode 100644 index 0000000000..15a511aebd --- /dev/null +++ b/third_party/objective_c/Cronet/cronet_c_for_grpc.h @@ -0,0 +1,202 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ +#define COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Cronet Engine API. */ + +/* Opaque object representing Cronet Engine. Created and configured outside + * of this API to facilitate sharing with other components */ +typedef struct cronet_engine { void* obj; } cronet_engine; + +void cronet_engine_add_quic_hint(cronet_engine* engine, + const char* host, + int port, + int alternate_port); + +/* Cronet Bidirectional Stream API */ + +/* Opaque object representing Cronet Bidirectional Stream. */ +typedef struct cronet_bidirectional_stream { + void* obj; + void* annotation; +} cronet_bidirectional_stream; + +/* A single request or response header element. */ +typedef struct cronet_bidirectional_stream_header { + const char* key; + const char* value; +} cronet_bidirectional_stream_header; + +/* Array of request or response headers or trailers. */ +typedef struct cronet_bidirectional_stream_header_array { + size_t count; + size_t capacity; + cronet_bidirectional_stream_header* headers; +} cronet_bidirectional_stream_header_array; + +/* Set of callbacks used to receive callbacks from bidirectional stream. */ +typedef struct cronet_bidirectional_stream_callback { + /* Invoked when request headers are sent. Indicates that stream has initiated + * the request. Consumer may call cronet_bidirectional_stream_write() to start + * writing data. + */ + void (*on_request_headers_sent)(cronet_bidirectional_stream* stream); + + /* Invoked when initial response headers are received. + * Consumer must call cronet_bidirectional_stream_read() to start reading. + * Consumer may call cronet_bidirectional_stream_write() to start writing or + * close the stream. Contents of |headers| is valid for duration of the call. + */ + void (*on_response_headers_received)( + cronet_bidirectional_stream* stream, + const cronet_bidirectional_stream_header_array* headers, + const char* negotiated_protocol); + + /* Invoked when data is read into the buffer passed to + * cronet_bidirectional_stream_read(). Only part of the buffer may be + * populated. To continue reading, call cronet_bidirectional_stream_read(). + * It may be invoked after on_response_trailers_received()}, if there was + * pending read data before trailers were received. + * + * If count is 0, it means the remote side has signaled that it will send no + * more data; future calls to cronet_bidirectional_stream_read() will result + * in the on_data_read() callback or on_succeded() callback if + * cronet_bidirectional_stream_write() was invoked with end_of_stream set to + * true. + */ + void (*on_read_completed)(cronet_bidirectional_stream* stream, + char* data, + int count); + + /** + * Invoked when all data passed to cronet_bidirectional_stream_write() is + * sent. + * To continue writing, call cronet_bidirectional_stream_write(). + */ + void (*on_write_completed)(cronet_bidirectional_stream* stream, + const char* data); + + /* Invoked when trailers are received before closing the stream. Only invoked + * when server sends trailers, which it may not. May be invoked while there is + * read data remaining in local buffer. Contents of |trailers| is valid for + * duration of the call. + */ + void (*on_response_trailers_received)( + cronet_bidirectional_stream* stream, + const cronet_bidirectional_stream_header_array* trailers); + + /** + * Invoked when there is no data to be read or written and the stream is + * closed successfully remotely and locally. Once invoked, no further callback + * methods will be invoked. + */ + void (*on_succeded)(cronet_bidirectional_stream* stream); + + /** + * Invoked if the stream failed for any reason after + * cronet_bidirectional_stream_start(). HTTP/2 error codes are + * mapped to chrome net error codes. Once invoked, no further callback methods + * will be invoked. + */ + void (*on_failed)(cronet_bidirectional_stream* stream, int net_error); + + /** + * Invoked if the stream was canceled via + * cronet_bidirectional_stream_cancel(). Once invoked, no further callback + * methods will be invoked. + */ + void (*on_canceled)(cronet_bidirectional_stream* stream); +} cronet_bidirectional_stream_callback; + +/* Create a new stream object that uses |engine| and |callback|. All stream + * tasks are performed asynchronously on the |engine| network thread. |callback| + * methods are invoked synchronously on the |engine| network thread, but must + * not run tasks on the current thread to prevent blocking networking operations + * and causing exceptions during shutdown. The |annotation| is stored in + * bidirectional stream for arbitrary use by application. + * + * Returned |cronet_bidirectional_stream*| is owned by the caller, and must be + * destroyed using |cronet_bidirectional_stream_destroy|. + * + * Both |calback| and |engine| must remain valid until stream is destroyed. + */ +cronet_bidirectional_stream* cronet_bidirectional_stream_create( + cronet_engine* engine, + void* annotation, + cronet_bidirectional_stream_callback* callback); + +/* TBD: The following methods return int. Should it be a custom type? */ + +/* Destroy stream object. Destroy could be called from any thread, including + * network thread, but is posted, so |stream| is valid until calling task is + * complete. + */ +int cronet_bidirectional_stream_destroy(cronet_bidirectional_stream* stream); + +/* Start the stream by sending request to |url| using |method| and |headers|. If + * |end_of_stream| is true, then no data is expected to be written. + */ +int cronet_bidirectional_stream_start( + cronet_bidirectional_stream* stream, + const char* url, + int priority, + const char* method, + const cronet_bidirectional_stream_header_array* headers, + bool end_of_stream); + +/* Read response data into |buffer| of |capacity| length. Must only be called at + * most once in response to each invocation of the + * on_response_headers_received() and on_read_completed() methods of the + * cronet_bidirectional_stream_callback. + * Each call will result in an invocation of one of the callback's + * on_read_completed method if data is read, its on_succeeded() method if + * the stream is closed, or its on_failed() method if there's an error. + */ +int cronet_bidirectional_stream_read(cronet_bidirectional_stream* stream, + char* buffer, + int capacity); + +/* Read response data into |buffer| of |capacity| length. Must only be called at + * most once in response to each invocation of the + * on_response_headers_received() and on_read_completed() methods of the + * cronet_bidirectional_stream_callback. + * Each call will result in an invocation of one of the callback's + * on_read_completed method if data is read, its on_succeeded() method if + * the stream is closed, or its on_failed() method if there's an error. + */ +int cronet_bidirectional_stream_write(cronet_bidirectional_stream* stream, + const char* buffer, + int count, + bool end_of_stream); + +/* Cancels the stream. Can be called at any time after + * cronet_bidirectional_stream_start(). The on_canceled() method of + * cronet_bidirectional_stream_callback will be invoked when cancelation + * is complete and no further callback methods will be invoked. If the + * stream has completed or has not started, calling + * cronet_bidirectional_stream_cancel() has no effect and on_canceled() will not + * be invoked. At most one callback method may be invoked after + * cronet_bidirectional_stream_cancel() has completed. + */ +int cronet_bidirectional_stream_cancel(cronet_bidirectional_stream* stream); + +/* Returns true if the |stream| was successfully started and is now done + * (succeeded, canceled, or failed). + * Returns false if the |stream| stream is not yet started or is in progress. + */ +bool cronet_bidirectional_stream_is_done(cronet_bidirectional_stream* stream); + +#ifdef __cplusplus +} +#endif + +#endif // COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index eed84252cc..aabca410da 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -786,6 +786,7 @@ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ +include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 7e0d5ebd37..ac919def65 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -786,6 +786,7 @@ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_win32.h \ include/grpc/impl/codegen/time.h \ +include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -913,6 +914,42 @@ src/core/ext/client_config/subchannel.h \ src/core/ext/client_config/subchannel_call_holder.h \ src/core/ext/client_config/subchannel_index.h \ src/core/ext/client_config/uri_parser.h \ +include/grpc/byte_buffer.h \ +include/grpc/grpc.h \ +include/grpc/impl/codegen/alloc.h \ +include/grpc/impl/codegen/atm.h \ +include/grpc/impl/codegen/atm_gcc_atomic.h \ +include/grpc/impl/codegen/atm_gcc_sync.h \ +include/grpc/impl/codegen/atm_win32.h \ +include/grpc/impl/codegen/byte_buffer.h \ +include/grpc/impl/codegen/compression_types.h \ +include/grpc/impl/codegen/connectivity_state.h \ +include/grpc/impl/codegen/grpc_types.h \ +include/grpc/impl/codegen/log.h \ +include/grpc/impl/codegen/port_platform.h \ +include/grpc/impl/codegen/propagation_bits.h \ +include/grpc/impl/codegen/slice.h \ +include/grpc/impl/codegen/slice_buffer.h \ +include/grpc/impl/codegen/status.h \ +include/grpc/impl/codegen/sync.h \ +include/grpc/impl/codegen/sync_generic.h \ +include/grpc/impl/codegen/sync_posix.h \ +include/grpc/impl/codegen/sync_win32.h \ +include/grpc/impl/codegen/time.h \ +include/grpc/status.h \ +include/grpc/support/alloc.h \ +include/grpc/support/atm.h \ +include/grpc/support/host_port.h \ +include/grpc/support/log.h \ +include/grpc/support/port_platform.h \ +include/grpc/support/slice.h \ +include/grpc/support/slice_buffer.h \ +include/grpc/support/string_util.h \ +include/grpc/support/sync.h \ +include/grpc/support/time.h \ +include/grpc/support/useful.h \ +src/core/lib/support/string.h \ +third_party/objective_c/Cronet/cronet_c_for_grpc.h \ src/core/ext/lb_policy/grpclb/load_balancer_api.h \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h \ third_party/nanopb/pb.h \ @@ -1071,6 +1108,9 @@ src/core/ext/client_config/subchannel_index.c \ src/core/ext/client_config/uri_parser.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ +src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ +src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ +src/core/ext/transport/cronet/transport/cronet_transport.c \ src/core/ext/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 8b1aa574e8..64358400fc 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -4157,7 +4157,8 @@ "grpc_transport_chttp2_client_insecure", "grpc_transport_chttp2_client_secure", "grpc_transport_chttp2_server_insecure", - "grpc_transport_chttp2_server_secure" + "grpc_transport_chttp2_server_secure", + "grpc_transport_cronet_client_secure" ], "headers": [], "language": "c", @@ -6031,6 +6032,7 @@ "tsi" ], "headers": [ + "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "src/core/lib/security/auth_filters.h", @@ -6046,6 +6048,7 @@ "language": "c", "name": "grpc_secure", "src": [ + "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "src/core/lib/http/httpcli_security_connector.c", @@ -6281,6 +6284,121 @@ "third_party": false, "type": "filegroup" }, + { + "deps": [], + "headers": [ + "include/grpc/byte_buffer.h", + "include/grpc/grpc.h", + "include/grpc/impl/codegen/alloc.h", + "include/grpc/impl/codegen/atm.h", + "include/grpc/impl/codegen/atm_gcc_atomic.h", + "include/grpc/impl/codegen/atm_gcc_sync.h", + "include/grpc/impl/codegen/atm_win32.h", + "include/grpc/impl/codegen/byte_buffer.h", + "include/grpc/impl/codegen/compression_types.h", + "include/grpc/impl/codegen/connectivity_state.h", + "include/grpc/impl/codegen/grpc_types.h", + "include/grpc/impl/codegen/log.h", + "include/grpc/impl/codegen/port_platform.h", + "include/grpc/impl/codegen/propagation_bits.h", + "include/grpc/impl/codegen/slice.h", + "include/grpc/impl/codegen/slice_buffer.h", + "include/grpc/impl/codegen/status.h", + "include/grpc/impl/codegen/sync.h", + "include/grpc/impl/codegen/sync_generic.h", + "include/grpc/impl/codegen/sync_posix.h", + "include/grpc/impl/codegen/sync_win32.h", + "include/grpc/impl/codegen/time.h", + "include/grpc/status.h", + "include/grpc/support/alloc.h", + "include/grpc/support/atm.h", + "include/grpc/support/host_port.h", + "include/grpc/support/log.h", + "include/grpc/support/port_platform.h", + "include/grpc/support/slice.h", + "include/grpc/support/slice_buffer.h", + "include/grpc/support/string_util.h", + "include/grpc/support/sync.h", + "include/grpc/support/time.h", + "include/grpc/support/useful.h", + "src/core/ext/transport/chttp2/transport/incoming_metadata.h", + "src/core/lib/channel/channel_stack.h", + "src/core/lib/channel/context.h", + "src/core/lib/debug/trace.h", + "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/exec_ctx.h", + "src/core/lib/iomgr/pollset.h", + "src/core/lib/iomgr/pollset_set.h", + "src/core/lib/support/string.h", + "src/core/lib/surface/channel.h", + "src/core/lib/surface/channel_stack_type.h", + "src/core/lib/transport/byte_stream.h", + "src/core/lib/transport/metadata.h", + "src/core/lib/transport/metadata_batch.h", + "src/core/lib/transport/transport.h", + "src/core/lib/transport/transport_impl.h", + "third_party/objective_c/Cronet/cronet_c_for_grpc.h" + ], + "language": "c", + "name": "grpc_transport_cronet_client_secure", + "src": [ + "include/grpc/byte_buffer.h", + "include/grpc/grpc.h", + "include/grpc/impl/codegen/alloc.h", + "include/grpc/impl/codegen/atm.h", + "include/grpc/impl/codegen/atm_gcc_atomic.h", + "include/grpc/impl/codegen/atm_gcc_sync.h", + "include/grpc/impl/codegen/atm_win32.h", + "include/grpc/impl/codegen/byte_buffer.h", + "include/grpc/impl/codegen/compression_types.h", + "include/grpc/impl/codegen/connectivity_state.h", + "include/grpc/impl/codegen/grpc_types.h", + "include/grpc/impl/codegen/log.h", + "include/grpc/impl/codegen/port_platform.h", + "include/grpc/impl/codegen/propagation_bits.h", + "include/grpc/impl/codegen/slice.h", + "include/grpc/impl/codegen/slice_buffer.h", + "include/grpc/impl/codegen/status.h", + "include/grpc/impl/codegen/sync.h", + "include/grpc/impl/codegen/sync_generic.h", + "include/grpc/impl/codegen/sync_posix.h", + "include/grpc/impl/codegen/sync_win32.h", + "include/grpc/impl/codegen/time.h", + "include/grpc/status.h", + "include/grpc/support/alloc.h", + "include/grpc/support/atm.h", + "include/grpc/support/host_port.h", + "include/grpc/support/log.h", + "include/grpc/support/port_platform.h", + "include/grpc/support/slice.h", + "include/grpc/support/slice_buffer.h", + "include/grpc/support/string_util.h", + "include/grpc/support/sync.h", + "include/grpc/support/time.h", + "include/grpc/support/useful.h", + "src/core/ext/transport/chttp2/transport/incoming_metadata.h", + "src/core/ext/transport/cronet/client/secure/cronet_channel_create.c", + "src/core/ext/transport/cronet/transport/cronet_api_dummy.c", + "src/core/ext/transport/cronet/transport/cronet_transport.c", + "src/core/lib/channel/channel_stack.h", + "src/core/lib/channel/context.h", + "src/core/lib/debug/trace.h", + "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/exec_ctx.h", + "src/core/lib/iomgr/pollset.h", + "src/core/lib/iomgr/pollset_set.h", + "src/core/lib/support/string.h", + "src/core/lib/surface/channel.h", + "src/core/lib/surface/channel_stack_type.h", + "src/core/lib/transport/byte_stream.h", + "src/core/lib/transport/metadata.h", + "src/core/lib/transport/metadata_batch.h", + "src/core/lib/transport/transport.h", + "src/core/lib/transport/transport_impl.h" + ], + "third_party": false, + "type": "filegroup" + }, { "deps": [], "headers": [ diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 6a2843e37c..932c2699f4 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -293,6 +293,7 @@ + @@ -422,6 +423,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -728,6 +765,12 @@ + + + + + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 7d53be719c..2dc192ed50 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -439,6 +439,15 @@ src\core\ext\transport\chttp2\client\insecure + + src\core\ext\transport\cronet\client\secure + + + src\core\ext\transport\cronet\transport + + + src\core\ext\transport\cronet\transport + src\core\ext\lb_policy\grpclb @@ -576,6 +585,9 @@ include\grpc\impl\codegen + + include\grpc + include\grpc @@ -959,6 +971,114 @@ src\core\ext\client_config + + include\grpc + + + include\grpc + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc\impl\codegen + + + include\grpc + + + include\grpc\support + + + include\grpc\support + + + include\grpc\support + + + include\grpc\support + + + include\grpc\support + + + include\grpc\support + + + include\grpc\support + + + include\grpc\support + + + include\grpc\support + + + include\grpc\support + + + include\grpc\support + + + src\core\lib\support + + + third_party\objective_c\Cronet + src\core\ext\lb_policy\grpclb @@ -1010,6 +1130,9 @@ {def748f5-ed2a-a9bb-40d9-c31d00f0e13b} + + {31de82ea-dc6c-73fb-a640-979b8a7b240c} + {d538af37-07b2-062b-fa2a-d9f882cb2737} @@ -1091,6 +1214,18 @@ {6f34254e-e69f-c9b4-156d-5024bade5408} + + {1e9c85e9-5522-7ef8-0017-7e19990a6194} + + + {d0530883-75d9-b5f7-d594-26735a70ac7b} + + + {4fa6fe90-b7a8-5c8f-d629-db1e68d89eed} + + + {31518af8-5860-6d0d-ff78-4059fce29ec2} + {5b2ded3f-84a5-f6b4-2060-286c7d1dc945} @@ -1115,6 +1250,9 @@ {c4661d64-349f-01c1-1ba8-0602f9047595} + + {27f30339-d694-40f5-db07-4b89b9aeea73} + {a21971fb-304f-da08-b1b2-7bd8df8ac373} @@ -1133,6 +1271,12 @@ {93d6596d-330c-1d27-6f84-3c840e57869e} + + {3a56a516-857e-d2aa-95cc-11685baf4e8c} + + + {a165c6e3-0776-6f40-7351-d7865668e220} + -- cgit v1.2.3 From 3fe71993daf16332e04eec4cbc48dbb2286e2f64 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Mon, 16 May 2016 12:06:10 +0000 Subject: Split and rename test_constants.PARALLELISM Going forward we'd like to be able to test much larger numbers of RPCs than the number of threads available to a test. --- src/python/grpcio/tests/unit/_cython/_channel_test.py | 2 +- .../grpcio/tests/unit/framework/common/test_constants.py | 9 +++++++-- .../interfaces/face/_blocking_invocation_inline_service.py | 10 +++++----- .../face/_future_invocation_asynchronous_event_service.py | 8 ++++---- 4 files changed, 17 insertions(+), 12 deletions(-) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/tests/unit/_cython/_channel_test.py b/src/python/grpcio/tests/unit/_cython/_channel_test.py index 931cd9083e..3dc7a246ae 100644 --- a/src/python/grpcio/tests/unit/_cython/_channel_test.py +++ b/src/python/grpcio/tests/unit/_cython/_channel_test.py @@ -60,7 +60,7 @@ def _create_loop_destroy(): def _in_parallel(behavior, arguments): threads = tuple( threading.Thread(target=behavior, args=arguments) - for _ in range(test_constants.PARALLELISM)) + for _ in range(test_constants.THREAD_CONCURRENCY)) for thread in threads: thread.start() for thread in threads: diff --git a/src/python/grpcio/tests/unit/framework/common/test_constants.py b/src/python/grpcio/tests/unit/framework/common/test_constants.py index 8d89101e09..b6682d396c 100644 --- a/src/python/grpcio/tests/unit/framework/common/test_constants.py +++ b/src/python/grpcio/tests/unit/framework/common/test_constants.py @@ -49,8 +49,13 @@ STREAM_LENGTH = 200 # The size of payloads to transmit in tests. PAYLOAD_SIZE = 256 * 1024 + 17 -# The parallelism to use in tests of parallel RPCs. -PARALLELISM = 200 +# The concurrency to use in tests of concurrent RPCs that will not create as +# many threads as RPCs. +RPC_CONCURRENCY = 200 + +# The concurrency to use in tests of concurrent RPCs that will create as many +# threads as RPCs. +THREAD_CONCURRENCY = 25 # The size of thread pools to use in tests. POOL_SIZE = 10 diff --git a/src/python/grpcio/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py b/src/python/grpcio/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py index 649892463a..e338aaa396 100644 --- a/src/python/grpcio/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py +++ b/src/python/grpcio/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py @@ -146,13 +146,13 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. test_messages.verify(second_request, second_response, self) def testParallelInvocations(self): - pool = logging_pool.pool(test_constants.PARALLELISM) + pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = [] response_futures = [] - for _ in range(test_constants.PARALLELISM): + for _ in range(test_constants.THREAD_CONCURRENCY): request = test_messages.request() response_future = pool.submit( self._invoker.blocking(group, method), request, @@ -168,13 +168,13 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. pool.shutdown(wait=True) def testWaitingForSomeButNotAllParallelInvocations(self): - pool = logging_pool.pool(test_constants.PARALLELISM) + pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = [] response_futures_to_indices = {} - for index in range(test_constants.PARALLELISM): + for index in range(test_constants.THREAD_CONCURRENCY): request = test_messages.request() response_future = pool.submit( self._invoker.blocking(group, method), request, @@ -184,7 +184,7 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. some_completed_response_futures_iterator = itertools.islice( futures.as_completed(response_futures_to_indices), - test_constants.PARALLELISM // 2) + test_constants.THREAD_CONCURRENCY // 2) for response_future in some_completed_response_futures_iterator: index = response_futures_to_indices[response_future] test_messages.verify(requests[index], response_future.result(), self) diff --git a/src/python/grpcio/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py b/src/python/grpcio/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py index c3813d5f3a..791620307b 100644 --- a/src/python/grpcio/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py +++ b/src/python/grpcio/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py @@ -249,7 +249,7 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. for test_messages in test_messages_sequence: requests = [] response_futures = [] - for _ in range(test_constants.PARALLELISM): + for _ in range(test_constants.THREAD_CONCURRENCY): request = test_messages.request() response_future = self._invoker.future(group, method)( request, test_constants.LONG_TIMEOUT) @@ -263,13 +263,13 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. test_messages.verify(request, response, self) def testWaitingForSomeButNotAllParallelInvocations(self): - pool = logging_pool.pool(test_constants.PARALLELISM) + pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) for (group, method), test_messages_sequence in ( six.iteritems(self._digest.unary_unary_messages_sequences)): for test_messages in test_messages_sequence: requests = [] response_futures_to_indices = {} - for index in range(test_constants.PARALLELISM): + for index in range(test_constants.THREAD_CONCURRENCY): request = test_messages.request() inner_response_future = self._invoker.future(group, method)( request, test_constants.LONG_TIMEOUT) @@ -279,7 +279,7 @@ class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest. some_completed_response_futures_iterator = itertools.islice( futures.as_completed(response_futures_to_indices), - test_constants.PARALLELISM // 2) + test_constants.THREAD_CONCURRENCY // 2) for response_future in some_completed_response_futures_iterator: index = response_futures_to_indices[response_future] test_messages.verify(requests[index], response_future.result(), self) -- cgit v1.2.3 From ea8ae0914293332a23b39668cf8413bdbdc3842f Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Mon, 16 May 2016 22:46:12 +0000 Subject: "sooner" -> "server" typo correction "... will not have the effect of stopping the sooner later", heh. :-P --- src/python/grpcio/grpc/beta/interfaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/grpc/beta/interfaces.py b/src/python/grpcio/grpc/beta/interfaces.py index 33ca45ac5b..24de9ad1a8 100644 --- a/src/python/grpcio/grpc/beta/interfaces.py +++ b/src/python/grpcio/grpc/beta/interfaces.py @@ -235,7 +235,7 @@ class Server(six.with_metaclass(abc.ABCMeta)): This method may be called at any time and is idempotent. Passing a smaller grace value than has been passed in a previous call will have the effect of stopping the Server sooner. Passing a larger grace value than has been - passed in a previous call will not have the effect of stopping the sooner + passed in a previous call will not have the effect of stopping the server later. Args: -- cgit v1.2.3 From 93cc06a48441a43c97fe7136839f70eab6355e99 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Fri, 13 May 2016 14:25:35 -0700 Subject: Add compression support to Cython layers --- src/python/grpcio/grpc/_adapter/_low.py | 20 +++--- src/python/grpcio/grpc/_adapter/_types.py | 4 +- src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi | 38 +++++++++++ .../grpcio/grpc/_cython/_cygrpc/records.pxd.pxi | 4 ++ .../grpcio/grpc/_cython/_cygrpc/records.pyx.pxi | 74 +++++++++++++++++++--- src/python/grpcio/grpc/_cython/imports.generated.h | 9 +-- .../grpcio/tests/unit/_cython/cygrpc_test.py | 58 ++++++++++------- .../grpc/_cython/imports.generated.h.template | 9 +-- 8 files changed, 167 insertions(+), 49 deletions(-) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/grpc/_adapter/_low.py b/src/python/grpcio/grpc/_adapter/_low.py index b13d8dd9dd..00788bd4cf 100644 --- a/src/python/grpcio/grpc/_adapter/_low.py +++ b/src/python/grpcio/grpc/_adapter/_low.py @@ -195,26 +195,30 @@ class Call(_types.Call): translated_op = cygrpc.operation_send_initial_metadata( cygrpc.Metadata( cygrpc.Metadatum(key, value) - for key, value in op.initial_metadata)) + for key, value in op.initial_metadata), + op.flags) elif op.type == _types.OpType.SEND_MESSAGE: - translated_op = cygrpc.operation_send_message(op.message) + translated_op = cygrpc.operation_send_message(op.message, op.flags) elif op.type == _types.OpType.SEND_CLOSE_FROM_CLIENT: - translated_op = cygrpc.operation_send_close_from_client() + translated_op = cygrpc.operation_send_close_from_client(op.flags) elif op.type == _types.OpType.SEND_STATUS_FROM_SERVER: translated_op = cygrpc.operation_send_status_from_server( cygrpc.Metadata( cygrpc.Metadatum(key, value) for key, value in op.trailing_metadata), op.status.code, - op.status.details) + op.status.details, + op.flags) elif op.type == _types.OpType.RECV_INITIAL_METADATA: - translated_op = cygrpc.operation_receive_initial_metadata() + translated_op = cygrpc.operation_receive_initial_metadata( + op.flags) elif op.type == _types.OpType.RECV_MESSAGE: - translated_op = cygrpc.operation_receive_message() + translated_op = cygrpc.operation_receive_message(op.flags) elif op.type == _types.OpType.RECV_STATUS_ON_CLIENT: - translated_op = cygrpc.operation_receive_status_on_client() + translated_op = cygrpc.operation_receive_status_on_client( + op.flags) elif op.type == _types.OpType.RECV_CLOSE_ON_SERVER: - translated_op = cygrpc.operation_receive_close_on_server() + translated_op = cygrpc.operation_receive_close_on_server(op.flags) else: raise ValueError('unexpected operation type {}'.format(op.type)) translated_ops.append(translated_op) diff --git a/src/python/grpcio/grpc/_adapter/_types.py b/src/python/grpcio/grpc/_adapter/_types.py index 8ca7ff4b60..f8405949d4 100644 --- a/src/python/grpcio/grpc/_adapter/_types.py +++ b/src/python/grpcio/grpc/_adapter/_types.py @@ -152,7 +152,7 @@ class OpArgs(collections.namedtuple( 'trailing_metadata', 'message', 'status', - 'write_flags', + 'flags', ])): """Arguments passed into a GRPC operation. @@ -165,7 +165,7 @@ class OpArgs(collections.namedtuple( message (bytes): Only valid if type == OpType.SEND_MESSAGE, else is None. status (Status): Only valid if type == OpType.SEND_STATUS_FROM_SERVER, else is None. - write_flags (int): a bit OR'ing of 0 or more OpWriteFlags values. + flags (int): a bitwise OR'ing of 0 or more OpWriteFlags values. """ @staticmethod diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index 3d158a7707..66e6e6b549 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -140,6 +140,9 @@ cdef extern from "grpc/_cython/loader.h": const char *GRPC_ARG_PRIMARY_USER_AGENT_STRING const char *GRPC_ARG_SECONDARY_USER_AGENT_STRING const char *GRPC_SSL_TARGET_NAME_OVERRIDE_ARG + const char *GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM + const char *GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL + const char *GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET const int GRPC_WRITE_BUFFER_HINT const int GRPC_WRITE_NO_COMPRESS @@ -425,3 +428,38 @@ cdef extern from "grpc/_cython/loader.h": grpc_call_credentials *grpc_metadata_credentials_create_from_plugin( grpc_metadata_credentials_plugin plugin, void *reserved) nogil + + ctypedef enum grpc_compression_algorithm: + GRPC_COMPRESS_NONE + GRPC_COMPRESS_DEFLATE + GRPC_COMPRESS_GZIP + GRPC_COMPRESS_ALGORITHMS_COUNT + + ctypedef enum grpc_compression_level: + GRPC_COMPRESS_LEVEL_NONE + GRPC_COMPRESS_LEVEL_LOW + GRPC_COMPRESS_LEVEL_MED + GRPC_COMPRESS_LEVEL_HIGH + GRPC_COMPRESS_LEVEL_COUNT + + ctypedef struct grpc_compression_options: + uint32_t enabled_algorithms_bitset + grpc_compression_algorithm default_compression_algorithm + + int grpc_compression_algorithm_parse( + const char *name, size_t name_length, + grpc_compression_algorithm *algorithm) nogil + int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm, + char **name) nogil + grpc_compression_algorithm grpc_compression_algorithm_for_level( + grpc_compression_level level, uint32_t accepted_encodings) nogil + void grpc_compression_options_init(grpc_compression_options *opts) nogil + void grpc_compression_options_enable_algorithm( + grpc_compression_options *opts, + grpc_compression_algorithm algorithm) nogil + void grpc_compression_options_disable_algorithm( + grpc_compression_options *opts, + grpc_compression_algorithm algorithm) nogil + int grpc_compression_options_is_algorithm_enabled( + const grpc_compression_options *opts, + grpc_compression_algorithm algorithm) nogil diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi index 30397818a1..0474697af8 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pxd.pxi @@ -124,3 +124,7 @@ cdef class Operations: cdef size_t c_nops cdef list operations + +cdef class CompressionOptions: + + cdef grpc_compression_options c_options diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi index c2202bdab2..c7539f0d49 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi @@ -103,6 +103,19 @@ class OperationType: receive_close_on_server = GRPC_OP_RECV_CLOSE_ON_SERVER +class CompressionAlgorithm: + none = GRPC_COMPRESS_NONE + deflate = GRPC_COMPRESS_DEFLATE + gzip = GRPC_COMPRESS_GZIP + + +class CompressionLevel: + none = GRPC_COMPRESS_LEVEL_NONE + low = GRPC_COMPRESS_LEVEL_LOW + medium = GRPC_COMPRESS_LEVEL_MED + high = GRPC_COMPRESS_LEVEL_HIGH + + cdef class Timespec: def __cinit__(self, time): @@ -472,6 +485,10 @@ cdef class Operation: def type(self): return self.c_op.type + @property + def flags(self): + return self.c_op.flags + @property def has_status(self): return self.c_op.type == GRPC_OP_RECV_STATUS_ON_CLIENT @@ -553,9 +570,10 @@ cdef class Operation: with nogil: gpr_free(self._received_status_details) -def operation_send_initial_metadata(Metadata metadata): +def operation_send_initial_metadata(Metadata metadata, int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_SEND_INITIAL_METADATA + op.c_op.flags = flags op.c_op.data.send_initial_metadata.count = metadata.c_metadata_array.count op.c_op.data.send_initial_metadata.metadata = ( metadata.c_metadata_array.metadata) @@ -563,23 +581,25 @@ def operation_send_initial_metadata(Metadata metadata): op.is_valid = True return op -def operation_send_message(data): +def operation_send_message(data, int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_SEND_MESSAGE + op.c_op.flags = flags byte_buffer = ByteBuffer(data) op.c_op.data.send_message = byte_buffer.c_byte_buffer op.references.append(byte_buffer) op.is_valid = True return op -def operation_send_close_from_client(): +def operation_send_close_from_client(int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_SEND_CLOSE_FROM_CLIENT + op.c_op.flags = flags op.is_valid = True return op def operation_send_status_from_server( - Metadata metadata, grpc_status_code code, details): + Metadata metadata, grpc_status_code code, details, int flags): if isinstance(details, bytes): pass elif isinstance(details, basestring): @@ -588,6 +608,7 @@ def operation_send_status_from_server( raise TypeError("expected a str or bytes object for details") cdef Operation op = Operation() op.c_op.type = GRPC_OP_SEND_STATUS_FROM_SERVER + op.c_op.flags = flags op.c_op.data.send_status_from_server.trailing_metadata_count = ( metadata.c_metadata_array.count) op.c_op.data.send_status_from_server.trailing_metadata = ( @@ -599,18 +620,20 @@ def operation_send_status_from_server( op.is_valid = True return op -def operation_receive_initial_metadata(): +def operation_receive_initial_metadata(int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_RECV_INITIAL_METADATA + op.c_op.flags = flags op._received_metadata = Metadata([]) op.c_op.data.receive_initial_metadata = ( &op._received_metadata.c_metadata_array) op.is_valid = True return op -def operation_receive_message(): +def operation_receive_message(int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_RECV_MESSAGE + op.c_op.flags = flags op._received_message = ByteBuffer(None) # n.b. the c_op.data.receive_message field needs to be deleted by us, # anyway, so we just let that be handled by the ByteBuffer() we allocated @@ -619,9 +642,10 @@ def operation_receive_message(): op.is_valid = True return op -def operation_receive_status_on_client(): +def operation_receive_status_on_client(int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_RECV_STATUS_ON_CLIENT + op.c_op.flags = flags op._received_metadata = Metadata([]) op.c_op.data.receive_status_on_client.trailing_metadata = ( &op._received_metadata.c_metadata_array) @@ -634,9 +658,10 @@ def operation_receive_status_on_client(): op.is_valid = True return op -def operation_receive_close_on_server(): +def operation_receive_close_on_server(int flags): cdef Operation op = Operation() op.c_op.type = GRPC_OP_RECV_CLOSE_ON_SERVER + op.c_op.flags = flags op.c_op.data.receive_close_on_server.cancelled = &op._received_cancelled op.is_valid = True return op @@ -692,3 +717,36 @@ cdef class Operations: def __iter__(self): return _OperationsIterator(self) + +cdef class CompressionOptions: + + def __cinit__(self): + with nogil: + grpc_compression_options_init(&self.c_options) + + def enable_algorithm(self, grpc_compression_algorithm algorithm): + with nogil: + grpc_compression_options_enable_algorithm(&self.c_options, algorithm) + + def disable_algorithm(self, grpc_compression_algorithm algorithm): + with nogil: + grpc_compression_options_disable_algorithm(&self.c_options, algorithm) + + def is_algorithm_enabled(self, grpc_compression_algorithm algorithm): + cdef int result + with nogil: + result = grpc_compression_options_is_algorithm_enabled( + &self.c_options, algorithm) + return result + + def to_channel_arg(self): + return ChannelArg(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET, + self.c_options.enabled_algorithms_bitset) + + +def compression_algorithm_name(grpc_compression_algorithm algorithm): + cdef char* name + with nogil: + grpc_compression_algorithm_name(algorithm, &name) + # Let Cython do the right thing with string casting + return name diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h index 54c8aaad13..6de295414a 100644 --- a/src/python/grpcio/grpc/_cython/imports.generated.h +++ b/src/python/grpcio/grpc/_cython/imports.generated.h @@ -870,14 +870,15 @@ void pygrpc_load_imports(HMODULE library); #else /* !GPR_WIN32 */ -#include -#include -#include -#include #include #include +#include #include #include +#include +#include +#include +#include #endif /* !GPR_WIN32 */ diff --git a/src/python/grpcio/tests/unit/_cython/cygrpc_test.py b/src/python/grpcio/tests/unit/_cython/cygrpc_test.py index 876da88de9..0a511101f0 100644 --- a/src/python/grpcio/tests/unit/_cython/cygrpc_test.py +++ b/src/python/grpcio/tests/unit/_cython/cygrpc_test.py @@ -40,6 +40,7 @@ from tests.unit import resources _SSL_HOST_OVERRIDE = 'foo.test.google.fr' _CALL_CREDENTIALS_METADATA_KEY = 'call-creds-key' _CALL_CREDENTIALS_METADATA_VALUE = 'call-creds-value' +_EMPTY_FLAGS = 0 def _metadata_plugin_callback(context, callback): callback(cygrpc.Metadata( @@ -76,7 +77,7 @@ class TypeSmokeTest(unittest.TestCase): def testOperationsIteration(self): operations = cygrpc.Operations([ - cygrpc.operation_send_message('asdf')]) + cygrpc.operation_send_message('asdf', _EMPTY_FLAGS)]) iterator = iter(operations) operation = next(iterator) self.assertIsInstance(operation, cygrpc.Operation) @@ -85,6 +86,11 @@ class TypeSmokeTest(unittest.TestCase): with self.assertRaises(StopIteration): next(iterator) + def testOperationFlags(self): + operation = cygrpc.operation_send_message('asdf', + cygrpc.WriteFlag.no_compress) + self.assertEqual(cygrpc.WriteFlag.no_compress, operation.flags) + def testTimespec(self): now = time.time() timespec = cygrpc.Timespec(now) @@ -188,12 +194,13 @@ class InsecureServerInsecureClient(unittest.TestCase): CLIENT_METADATA_ASCII_VALUE), cygrpc.Metadatum(CLIENT_METADATA_BIN_KEY, CLIENT_METADATA_BIN_VALUE)]) client_start_batch_result = client_call.start_batch(cygrpc.Operations([ - cygrpc.operation_send_initial_metadata(client_initial_metadata), - cygrpc.operation_send_message(REQUEST), - cygrpc.operation_send_close_from_client(), - cygrpc.operation_receive_initial_metadata(), - cygrpc.operation_receive_message(), - cygrpc.operation_receive_status_on_client() + cygrpc.operation_send_initial_metadata(client_initial_metadata, + _EMPTY_FLAGS), + cygrpc.operation_send_message(REQUEST, _EMPTY_FLAGS), + cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), + cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), + cygrpc.operation_receive_message(_EMPTY_FLAGS), + cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS) ]), client_call_tag) self.assertEqual(cygrpc.CallError.ok, client_start_batch_result) client_event_future = test_utilities.CompletionQueuePollFuture( @@ -223,12 +230,14 @@ class InsecureServerInsecureClient(unittest.TestCase): cygrpc.Metadatum(SERVER_TRAILING_METADATA_KEY, SERVER_TRAILING_METADATA_VALUE)]) server_start_batch_result = server_call.start_batch([ - cygrpc.operation_send_initial_metadata(server_initial_metadata), - cygrpc.operation_receive_message(), - cygrpc.operation_send_message(RESPONSE), - cygrpc.operation_receive_close_on_server(), + cygrpc.operation_send_initial_metadata(server_initial_metadata, + _EMPTY_FLAGS), + cygrpc.operation_receive_message(_EMPTY_FLAGS), + cygrpc.operation_send_message(RESPONSE, _EMPTY_FLAGS), + cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), cygrpc.operation_send_status_from_server( - server_trailing_metadata, SERVER_STATUS_CODE, SERVER_STATUS_DETAILS) + server_trailing_metadata, SERVER_STATUS_CODE, + SERVER_STATUS_DETAILS, _EMPTY_FLAGS) ], server_call_tag) self.assertEqual(cygrpc.CallError.ok, server_start_batch_result) @@ -349,12 +358,13 @@ class SecureServerSecureClient(unittest.TestCase): CLIENT_METADATA_ASCII_VALUE), cygrpc.Metadatum(CLIENT_METADATA_BIN_KEY, CLIENT_METADATA_BIN_VALUE)]) client_start_batch_result = client_call.start_batch(cygrpc.Operations([ - cygrpc.operation_send_initial_metadata(client_initial_metadata), - cygrpc.operation_send_message(REQUEST), - cygrpc.operation_send_close_from_client(), - cygrpc.operation_receive_initial_metadata(), - cygrpc.operation_receive_message(), - cygrpc.operation_receive_status_on_client() + cygrpc.operation_send_initial_metadata(client_initial_metadata, + _EMPTY_FLAGS), + cygrpc.operation_send_message(REQUEST, _EMPTY_FLAGS), + cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), + cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), + cygrpc.operation_receive_message(_EMPTY_FLAGS), + cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS) ]), client_call_tag) self.assertEqual(cygrpc.CallError.ok, client_start_batch_result) client_event_future = test_utilities.CompletionQueuePollFuture( @@ -387,12 +397,14 @@ class SecureServerSecureClient(unittest.TestCase): cygrpc.Metadatum(SERVER_TRAILING_METADATA_KEY, SERVER_TRAILING_METADATA_VALUE)]) server_start_batch_result = server_call.start_batch([ - cygrpc.operation_send_initial_metadata(server_initial_metadata), - cygrpc.operation_receive_message(), - cygrpc.operation_send_message(RESPONSE), - cygrpc.operation_receive_close_on_server(), + cygrpc.operation_send_initial_metadata(server_initial_metadata, + _EMPTY_FLAGS), + cygrpc.operation_receive_message(_EMPTY_FLAGS), + cygrpc.operation_send_message(RESPONSE, _EMPTY_FLAGS), + cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), cygrpc.operation_send_status_from_server( - server_trailing_metadata, SERVER_STATUS_CODE, SERVER_STATUS_DETAILS) + server_trailing_metadata, SERVER_STATUS_CODE, + SERVER_STATUS_DETAILS, _EMPTY_FLAGS) ], server_call_tag) self.assertEqual(cygrpc.CallError.ok, server_start_batch_result) diff --git a/templates/src/python/grpcio/grpc/_cython/imports.generated.h.template b/templates/src/python/grpcio/grpc/_cython/imports.generated.h.template index 8e7c183180..26e717e58d 100644 --- a/templates/src/python/grpcio/grpc/_cython/imports.generated.h.template +++ b/templates/src/python/grpcio/grpc/_cython/imports.generated.h.template @@ -64,14 +64,15 @@ #else /* !GPR_WIN32 */ - #include - #include - #include - #include #include #include + #include #include #include + #include + #include + #include + #include #endif /* !GPR_WIN32 */ -- cgit v1.2.3 From 824ad2a5b9943c35933a675688634c2f152fd340 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Thu, 19 May 2016 20:56:14 +0000 Subject: "taking a this" -> "taking this" typo correction --- src/python/grpcio/grpc/framework/foundation/future.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/grpc/framework/foundation/future.py b/src/python/grpcio/grpc/framework/foundation/future.py index 9210616150..6fb58eadb6 100644 --- a/src/python/grpcio/grpc/framework/foundation/future.py +++ b/src/python/grpcio/grpc/framework/foundation/future.py @@ -232,6 +232,6 @@ class Future(six.with_metaclass(abc.ABCMeta)): immediately. Args: - fn: A callable taking a this Future object as its single parameter. + fn: A callable taking this Future object as its single parameter. """ raise NotImplementedError() -- cgit v1.2.3 From d88e15cee750cd647a900098d82f87cc25aa8dbe Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 20 May 2016 12:22:37 -0700 Subject: Remove legacy poller --- BUILD | 6 - Makefile | 2 - binding.gyp | 1 - build.yaml | 2 - config.m4 | 1 - gRPC.podspec | 3 - grpc.gemspec | 2 - package.xml | 2 - src/core/lib/iomgr/ev_poll_and_epoll_posix.c | 1978 -------------------- src/core/lib/iomgr/ev_poll_and_epoll_posix.h | 41 - src/core/lib/iomgr/ev_poll_posix.c | 2 + src/core/lib/iomgr/ev_posix.c | 3 +- src/python/grpcio/grpc_core_dependencies.py | 1 - third_party/protobuf | 2 +- tools/doxygen/Doxyfile.core.internal | 2 - tools/run_tests/run_tests.py | 2 +- tools/run_tests/sources_and_headers.json | 3 - vsprojects/vcxproj/grpc/grpc.vcxproj | 3 - vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 6 - .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 3 - .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 - 21 files changed, 5 insertions(+), 2066 deletions(-) delete mode 100644 src/core/lib/iomgr/ev_poll_and_epoll_posix.c delete mode 100644 src/core/lib/iomgr/ev_poll_and_epoll_posix.h (limited to 'src/python/grpcio') diff --git a/BUILD b/BUILD index 793c1c714d..0f8d8c7710 100644 --- a/BUILD +++ b/BUILD @@ -178,7 +178,6 @@ cc_library( "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", - "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -313,7 +312,6 @@ cc_library( "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", - "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -531,7 +529,6 @@ cc_library( "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", - "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -652,7 +649,6 @@ cc_library( "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", - "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -1345,7 +1341,6 @@ objc_library( "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", - "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -1542,7 +1537,6 @@ objc_library( "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", - "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", diff --git a/Makefile b/Makefile index c93c9a4241..949f8669c7 100644 --- a/Makefile +++ b/Makefile @@ -2510,7 +2510,6 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ - src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -2857,7 +2856,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ - src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ diff --git a/binding.gyp b/binding.gyp index 760bb24d72..442a14762c 100644 --- a/binding.gyp +++ b/binding.gyp @@ -581,7 +581,6 @@ 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', - 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', diff --git a/build.yaml b/build.yaml index 68e814f76c..acf2f9307f 100644 --- a/build.yaml +++ b/build.yaml @@ -165,7 +165,6 @@ filegroups: - src/core/lib/iomgr/closure.h - src/core/lib/iomgr/endpoint.h - src/core/lib/iomgr/endpoint_pair.h - - src/core/lib/iomgr/ev_poll_and_epoll_posix.h - src/core/lib/iomgr/ev_poll_posix.h - src/core/lib/iomgr/ev_posix.h - src/core/lib/iomgr/exec_ctx.h @@ -240,7 +239,6 @@ filegroups: - src/core/lib/iomgr/endpoint.c - src/core/lib/iomgr/endpoint_pair_posix.c - src/core/lib/iomgr/endpoint_pair_windows.c - - src/core/lib/iomgr/ev_poll_and_epoll_posix.c - src/core/lib/iomgr/ev_poll_posix.c - src/core/lib/iomgr/ev_posix.c - src/core/lib/iomgr/exec_ctx.c diff --git a/config.m4 b/config.m4 index 6ed1887fef..8f2cfa24a4 100644 --- a/config.m4 +++ b/config.m4 @@ -100,7 +100,6 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ - src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ diff --git a/gRPC.podspec b/gRPC.podspec index 67e7a8174f..ea02aa3487 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -181,7 +181,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', - 'src/core/lib/iomgr/ev_poll_and_epoll_posix.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', @@ -350,7 +349,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', - 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', @@ -531,7 +529,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', - 'src/core/lib/iomgr/ev_poll_and_epoll_posix.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', diff --git a/grpc.gemspec b/grpc.gemspec index 13aed6b61c..72f044258b 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -190,7 +190,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/closure.h ) s.files += %w( src/core/lib/iomgr/endpoint.h ) s.files += %w( src/core/lib/iomgr/endpoint_pair.h ) - s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.h ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.h ) s.files += %w( src/core/lib/iomgr/ev_posix.h ) s.files += %w( src/core/lib/iomgr/exec_ctx.h ) @@ -329,7 +328,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/endpoint.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_posix.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c ) - s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.c ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.c ) s.files += %w( src/core/lib/iomgr/ev_posix.c ) s.files += %w( src/core/lib/iomgr/exec_ctx.c ) diff --git a/package.xml b/package.xml index a169ad24e7..a9b0ee4be2 100644 --- a/package.xml +++ b/package.xml @@ -197,7 +197,6 @@ - @@ -336,7 +335,6 @@ - diff --git a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c b/src/core/lib/iomgr/ev_poll_and_epoll_posix.c deleted file mode 100644 index 943c404f91..0000000000 --- a/src/core/lib/iomgr/ev_poll_and_epoll_posix.c +++ /dev/null @@ -1,1978 +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. - * - */ - -/* This file will be removed shortly: it's here to keep refactoring - * steps simple and auditable. - * It's the combination of the old files: - * - fd_posix.{h,c} - * - pollset_posix.{h,c} - * - pullset_multipoller_with_{poll,epoll}.{h,c} - * The new version will be split into: - * - ev_poll_posix.{h,c} - * - ev_epoll_posix.{h,c} - */ - -#include - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/lib/iomgr/ev_poll_and_epoll_posix.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/iomgr_internal.h" -#include "src/core/lib/iomgr/wakeup_fd_posix.h" -#include "src/core/lib/profiling/timers.h" -#include "src/core/lib/support/block_annotate.h" - -/******************************************************************************* - * FD declarations - */ - -typedef struct grpc_fd_watcher { - struct grpc_fd_watcher *next; - struct grpc_fd_watcher *prev; - grpc_pollset *pollset; - grpc_pollset_worker *worker; - grpc_fd *fd; -} grpc_fd_watcher; - -struct grpc_fd { - int fd; - /* refst format: - bit0: 1=active/0=orphaned - bit1-n: refcount - meaning that mostly we ref by two to avoid altering the orphaned bit, - and just unref by 1 when we're ready to flag the object as orphaned */ - gpr_atm refst; - - gpr_mu mu; - int shutdown; - int closed; - int released; - - /* The watcher list. - - The following watcher related fields are protected by watcher_mu. - - An fd_watcher is an ephemeral object created when an fd wants to - begin polling, and destroyed after the poll. - - It denotes the fd's interest in whether to read poll or write poll - or both or neither on this fd. - - If a watcher is asked to poll for reads or writes, the read_watcher - or write_watcher fields are set respectively. A watcher may be asked - to poll for both, in which case both fields will be set. - - read_watcher and write_watcher may be NULL if no watcher has been - asked to poll for reads or writes. - - If an fd_watcher is not asked to poll for reads or writes, it's added - to a linked list of inactive watchers, rooted at inactive_watcher_root. - If at a later time there becomes need of a poller to poll, one of - the inactive pollers may be kicked out of their poll loops to take - that responsibility. */ - grpc_fd_watcher inactive_watcher_root; - grpc_fd_watcher *read_watcher; - grpc_fd_watcher *write_watcher; - - grpc_closure *read_closure; - grpc_closure *write_closure; - - struct grpc_fd *freelist_next; - - grpc_closure *on_done_closure; - - grpc_iomgr_object iomgr_object; - - /* The pollset that last noticed and notified that the fd is readable */ - grpc_pollset *read_notifier_pollset; -}; - -/* Begin polling on an fd. - Registers that the given pollset is interested in this fd - so that if read - or writability interest changes, the pollset can be kicked to pick up that - new interest. - Return value is: - (fd_needs_read? read_mask : 0) | (fd_needs_write? write_mask : 0) - i.e. a combination of read_mask and write_mask determined by the fd's current - interest in said events. - Polling strategies that do not need to alter their behavior depending on the - fd's current interest (such as epoll) do not need to call this function. - MUST NOT be called with a pollset lock taken */ -static uint32_t fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, - grpc_pollset_worker *worker, uint32_t read_mask, - uint32_t write_mask, grpc_fd_watcher *rec); -/* Complete polling previously started with fd_begin_poll - MUST NOT be called with a pollset lock taken - if got_read or got_write are 1, also does the become_{readable,writable} as - appropriate. */ -static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *rec, - int got_read, int got_write, - grpc_pollset *read_notifier_pollset); - -/* Return 1 if this fd is orphaned, 0 otherwise */ -static bool fd_is_orphaned(grpc_fd *fd); - -/* Reference counting for fds */ -/*#define GRPC_FD_REF_COUNT_DEBUG*/ -#ifdef GRPC_FD_REF_COUNT_DEBUG -static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line); -static void fd_unref(grpc_fd *fd, const char *reason, const char *file, - int line); -#define GRPC_FD_REF(fd, reason) fd_ref(fd, reason, __FILE__, __LINE__) -#define GRPC_FD_UNREF(fd, reason) fd_unref(fd, reason, __FILE__, __LINE__) -#else -static void fd_ref(grpc_fd *fd); -static void fd_unref(grpc_fd *fd); -#define GRPC_FD_REF(fd, reason) fd_ref(fd) -#define GRPC_FD_UNREF(fd, reason) fd_unref(fd) -#endif - -static void fd_global_init(void); -static void fd_global_shutdown(void); - -#define CLOSURE_NOT_READY ((grpc_closure *)0) -#define CLOSURE_READY ((grpc_closure *)1) - -/******************************************************************************* - * pollset declarations - */ - -typedef struct grpc_pollset_vtable grpc_pollset_vtable; - -typedef struct grpc_cached_wakeup_fd { - grpc_wakeup_fd fd; - struct grpc_cached_wakeup_fd *next; -} grpc_cached_wakeup_fd; - -struct grpc_pollset_worker { - grpc_cached_wakeup_fd *wakeup_fd; - int reevaluate_polling_on_wakeup; - int kicked_specifically; - struct grpc_pollset_worker *next; - struct grpc_pollset_worker *prev; -}; - -struct grpc_pollset { - /* pollsets under posix can mutate representation as fds are added and - removed. - For example, we may choose a poll() based implementation on linux for - few fds, and an epoll() based implementation for many fds */ - const grpc_pollset_vtable *vtable; - gpr_mu mu; - grpc_pollset_worker root_worker; - int in_flight_cbs; - int shutting_down; - int called_shutdown; - int kicked_without_pollers; - grpc_closure *shutdown_done; - grpc_closure_list idle_jobs; - union { - int fd; - void *ptr; - } data; - /* Local cache of eventfds for workers */ - grpc_cached_wakeup_fd *local_wakeup_cache; -}; - -struct grpc_pollset_vtable { - void (*add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - struct grpc_fd *fd, int and_unlock_pollset); - void (*maybe_work_and_unlock)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_pollset_worker *worker, - gpr_timespec deadline, gpr_timespec now); - void (*finish_shutdown)(grpc_pollset *pollset); - void (*destroy)(grpc_pollset *pollset); -}; - -/* Add an fd to a pollset */ -static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - struct grpc_fd *fd); - -static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, grpc_fd *fd); - -/* Convert a timespec to milliseconds: - - very small or negative poll times are clamped to zero to do a - non-blocking poll (which becomes spin polling) - - other small values are rounded up to one millisecond - - longer than a millisecond polls are rounded up to the next nearest - millisecond to avoid spinning - - infinite timeouts are converted to -1 */ -static int poll_deadline_to_millis_timeout(gpr_timespec deadline, - gpr_timespec now); - -/* Allow kick to wakeup the currently polling worker */ -#define GRPC_POLLSET_CAN_KICK_SELF 1 -/* Force the wakee to repoll when awoken */ -#define GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP 2 -/* As per pollset_kick, with an extended set of flags (defined above) - -- mostly for fd_posix's use. */ -static void pollset_kick_ext(grpc_pollset *p, - grpc_pollset_worker *specific_worker, - uint32_t flags); - -/* turn a pollset into a multipoller: platform specific */ -typedef void (*platform_become_multipoller_type)(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, - struct grpc_fd **fds, - size_t fd_count); -static platform_become_multipoller_type platform_become_multipoller; - -/* Return 1 if the pollset has active threads in pollset_work (pollset must - * be locked) */ -static int pollset_has_workers(grpc_pollset *pollset); - -static void remove_fd_from_all_epoll_sets(int fd); - -/******************************************************************************* - * pollset_set definitions - */ - -struct grpc_pollset_set { - gpr_mu mu; - - size_t pollset_count; - size_t pollset_capacity; - grpc_pollset **pollsets; - - size_t pollset_set_count; - size_t pollset_set_capacity; - struct grpc_pollset_set **pollset_sets; - - size_t fd_count; - size_t fd_capacity; - grpc_fd **fds; -}; - -/******************************************************************************* - * fd_posix.c - */ - -/* We need to keep a freelist not because of any concerns of malloc performance - * but instead so that implementations with multiple threads in (for example) - * epoll_wait deal with the race between pollset removal and incoming poll - * notifications. - * - * The problem is that the poller ultimately holds a reference to this - * object, so it is very difficult to know when is safe to free it, at least - * without some expensive synchronization. - * - * If we keep the object freelisted, in the worst case losing this race just - * becomes a spurious read notification on a reused fd. - */ -/* TODO(klempner): We could use some form of polling generation count to know - * when these are safe to free. */ -/* TODO(klempner): Consider disabling freelisting if we don't have multiple - * threads in poll on the same fd */ -/* TODO(klempner): Batch these allocations to reduce fragmentation */ -static grpc_fd *fd_freelist = NULL; -static gpr_mu fd_freelist_mu; - -static void freelist_fd(grpc_fd *fd) { - gpr_mu_lock(&fd_freelist_mu); - fd->freelist_next = fd_freelist; - fd_freelist = fd; - grpc_iomgr_unregister_object(&fd->iomgr_object); - gpr_mu_unlock(&fd_freelist_mu); -} - -static grpc_fd *alloc_fd(int fd) { - grpc_fd *r = NULL; - gpr_mu_lock(&fd_freelist_mu); - if (fd_freelist != NULL) { - r = fd_freelist; - fd_freelist = fd_freelist->freelist_next; - } - gpr_mu_unlock(&fd_freelist_mu); - if (r == NULL) { - r = gpr_malloc(sizeof(grpc_fd)); - gpr_mu_init(&r->mu); - } - - gpr_mu_lock(&r->mu); - gpr_atm_rel_store(&r->refst, 1); - r->shutdown = 0; - r->read_closure = CLOSURE_NOT_READY; - r->write_closure = CLOSURE_NOT_READY; - r->fd = fd; - r->inactive_watcher_root.next = r->inactive_watcher_root.prev = - &r->inactive_watcher_root; - r->freelist_next = NULL; - r->read_watcher = r->write_watcher = NULL; - r->on_done_closure = NULL; - r->closed = 0; - r->released = 0; - r->read_notifier_pollset = NULL; - gpr_mu_unlock(&r->mu); - return r; -} - -static void destroy(grpc_fd *fd) { - gpr_mu_destroy(&fd->mu); - gpr_free(fd); -} - -#ifdef GRPC_FD_REF_COUNT_DEBUG -#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) -#define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) -static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, - int line) { - gpr_log(GPR_DEBUG, "FD %d %p ref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, - gpr_atm_no_barrier_load(&fd->refst), - gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); -#else -#define REF_BY(fd, n, reason) ref_by(fd, n) -#define UNREF_BY(fd, n, reason) unref_by(fd, n) -static void ref_by(grpc_fd *fd, int n) { -#endif - GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); -} - -#ifdef GRPC_FD_REF_COUNT_DEBUG -static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file, - int line) { - gpr_atm old; - gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n, - gpr_atm_no_barrier_load(&fd->refst), - gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); -#else -static void unref_by(grpc_fd *fd, int n) { - gpr_atm old; -#endif - old = gpr_atm_full_fetch_add(&fd->refst, -n); - if (old == n) { - freelist_fd(fd); - } else { - GPR_ASSERT(old > n); - } -} - -static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); } - -static void fd_global_shutdown(void) { - gpr_mu_lock(&fd_freelist_mu); - gpr_mu_unlock(&fd_freelist_mu); - while (fd_freelist != NULL) { - grpc_fd *fd = fd_freelist; - fd_freelist = fd_freelist->freelist_next; - destroy(fd); - } - gpr_mu_destroy(&fd_freelist_mu); -} - -static grpc_fd *fd_create(int fd, const char *name) { - grpc_fd *r = alloc_fd(fd); - char *name2; - gpr_asprintf(&name2, "%s fd=%d", name, fd); - grpc_iomgr_register_object(&r->iomgr_object, name2); - gpr_free(name2); -#ifdef GRPC_FD_REF_COUNT_DEBUG - gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, r, name); -#endif - return r; -} - -static bool fd_is_orphaned(grpc_fd *fd) { - return (gpr_atm_acq_load(&fd->refst) & 1) == 0; -} - -static void pollset_kick_locked(grpc_fd_watcher *watcher) { - gpr_mu_lock(&watcher->pollset->mu); - GPR_ASSERT(watcher->worker); - pollset_kick_ext(watcher->pollset, watcher->worker, - GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP); - gpr_mu_unlock(&watcher->pollset->mu); -} - -static void maybe_wake_one_watcher_locked(grpc_fd *fd) { - if (fd->inactive_watcher_root.next != &fd->inactive_watcher_root) { - pollset_kick_locked(fd->inactive_watcher_root.next); - } else if (fd->read_watcher) { - pollset_kick_locked(fd->read_watcher); - } else if (fd->write_watcher) { - pollset_kick_locked(fd->write_watcher); - } -} - -static void wake_all_watchers_locked(grpc_fd *fd) { - grpc_fd_watcher *watcher; - for (watcher = fd->inactive_watcher_root.next; - watcher != &fd->inactive_watcher_root; watcher = watcher->next) { - pollset_kick_locked(watcher); - } - if (fd->read_watcher) { - pollset_kick_locked(fd->read_watcher); - } - if (fd->write_watcher && fd->write_watcher != fd->read_watcher) { - pollset_kick_locked(fd->write_watcher); - } -} - -static int has_watchers(grpc_fd *fd) { - return fd->read_watcher != NULL || fd->write_watcher != NULL || - fd->inactive_watcher_root.next != &fd->inactive_watcher_root; -} - -static void close_fd_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - fd->closed = 1; - if (!fd->released) { - close(fd->fd); - } else { - remove_fd_from_all_epoll_sets(fd->fd); - } - grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, true, NULL); -} - -static int fd_wrapped_fd(grpc_fd *fd) { - if (fd->released || fd->closed) { - return -1; - } else { - return fd->fd; - } -} - -static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure *on_done, int *release_fd, - const char *reason) { - fd->on_done_closure = on_done; - fd->released = release_fd != NULL; - if (!fd->released) { - shutdown(fd->fd, SHUT_RDWR); - } else { - *release_fd = fd->fd; - } - gpr_mu_lock(&fd->mu); - REF_BY(fd, 1, reason); /* remove active status, but keep referenced */ - if (!has_watchers(fd)) { - close_fd_locked(exec_ctx, fd); - } else { - wake_all_watchers_locked(fd); - } - gpr_mu_unlock(&fd->mu); - UNREF_BY(fd, 2, reason); /* drop the reference */ -} - -/* increment refcount by two to avoid changing the orphan bit */ -#ifdef GRPC_FD_REF_COUNT_DEBUG -static void fd_ref(grpc_fd *fd, const char *reason, const char *file, - int line) { - ref_by(fd, 2, reason, file, line); -} - -static void fd_unref(grpc_fd *fd, const char *reason, const char *file, - int line) { - unref_by(fd, 2, reason, file, line); -} -#else -static void fd_ref(grpc_fd *fd) { ref_by(fd, 2); } - -static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); } -#endif - -static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure **st, grpc_closure *closure) { - if (*st == CLOSURE_NOT_READY) { - /* not ready ==> switch to a waiting state by setting the closure */ - *st = closure; - } else if (*st == CLOSURE_READY) { - /* already ready ==> queue the closure to run immediately */ - *st = CLOSURE_NOT_READY; - grpc_exec_ctx_enqueue(exec_ctx, closure, !fd->shutdown, NULL); - maybe_wake_one_watcher_locked(fd); - } else { - /* upcallptr was set to a different closure. This is an error! */ - gpr_log(GPR_ERROR, - "User called a notify_on function with a previous callback still " - "pending"); - abort(); - } -} - -/* returns 1 if state becomes not ready */ -static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure **st) { - if (*st == CLOSURE_READY) { - /* duplicate ready ==> ignore */ - return 0; - } else if (*st == CLOSURE_NOT_READY) { - /* not ready, and not waiting ==> flag ready */ - *st = CLOSURE_READY; - return 0; - } else { - /* waiting ==> queue closure */ - grpc_exec_ctx_enqueue(exec_ctx, *st, !fd->shutdown, NULL); - *st = CLOSURE_NOT_READY; - return 1; - } -} - -static void set_read_notifier_pollset_locked( - grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_pollset *read_notifier_pollset) { - fd->read_notifier_pollset = read_notifier_pollset; -} - -static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - gpr_mu_lock(&fd->mu); - GPR_ASSERT(!fd->shutdown); - fd->shutdown = 1; - set_ready_locked(exec_ctx, fd, &fd->read_closure); - set_ready_locked(exec_ctx, fd, &fd->write_closure); - gpr_mu_unlock(&fd->mu); -} - -static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure *closure) { - gpr_mu_lock(&fd->mu); - notify_on_locked(exec_ctx, fd, &fd->read_closure, closure); - gpr_mu_unlock(&fd->mu); -} - -static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_closure *closure) { - gpr_mu_lock(&fd->mu); - notify_on_locked(exec_ctx, fd, &fd->write_closure, closure); - gpr_mu_unlock(&fd->mu); -} - -/* Return the read-notifier pollset */ -static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, - grpc_fd *fd) { - grpc_pollset *notifier = NULL; - - gpr_mu_lock(&fd->mu); - notifier = fd->read_notifier_pollset; - gpr_mu_unlock(&fd->mu); - - return notifier; -} - -static uint32_t fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, - grpc_pollset_worker *worker, uint32_t read_mask, - uint32_t write_mask, grpc_fd_watcher *watcher) { - uint32_t mask = 0; - grpc_closure *cur; - int requested; - /* keep track of pollers that have requested our events, in case they change - */ - GRPC_FD_REF(fd, "poll"); - - gpr_mu_lock(&fd->mu); - - /* if we are shutdown, then don't add to the watcher set */ - if (fd->shutdown) { - watcher->fd = NULL; - watcher->pollset = NULL; - watcher->worker = NULL; - gpr_mu_unlock(&fd->mu); - GRPC_FD_UNREF(fd, "poll"); - return 0; - } - - /* if there is nobody polling for read, but we need to, then start doing so */ - cur = fd->read_closure; - requested = cur != CLOSURE_READY; - if (read_mask && fd->read_watcher == NULL && requested) { - fd->read_watcher = watcher; - mask |= read_mask; - } - /* if there is nobody polling for write, but we need to, then start doing so - */ - cur = fd->write_closure; - requested = cur != CLOSURE_READY; - if (write_mask && fd->write_watcher == NULL && requested) { - fd->write_watcher = watcher; - mask |= write_mask; - } - /* if not polling, remember this watcher in case we need someone to later */ - if (mask == 0 && worker != NULL) { - watcher->next = &fd->inactive_watcher_root; - watcher->prev = watcher->next->prev; - watcher->next->prev = watcher->prev->next = watcher; - } - watcher->pollset = pollset; - watcher->worker = worker; - watcher->fd = fd; - gpr_mu_unlock(&fd->mu); - - return mask; -} - -static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *watcher, - int got_read, int got_write, - grpc_pollset *read_notifier_pollset) { - int was_polling = 0; - int kick = 0; - grpc_fd *fd = watcher->fd; - - if (fd == NULL) { - return; - } - - gpr_mu_lock(&fd->mu); - - if (watcher == fd->read_watcher) { - /* remove read watcher, kick if we still need a read */ - was_polling = 1; - if (!got_read) { - kick = 1; - } - fd->read_watcher = NULL; - } - if (watcher == fd->write_watcher) { - /* remove write watcher, kick if we still need a write */ - was_polling = 1; - if (!got_write) { - kick = 1; - } - fd->write_watcher = NULL; - } - if (!was_polling && watcher->worker != NULL) { - /* remove from inactive list */ - watcher->next->prev = watcher->prev; - watcher->prev->next = watcher->next; - } - if (got_read) { - if (set_ready_locked(exec_ctx, fd, &fd->read_closure)) { - kick = 1; - } - - if (read_notifier_pollset != NULL) { - set_read_notifier_pollset_locked(exec_ctx, fd, read_notifier_pollset); - } - } - if (got_write) { - if (set_ready_locked(exec_ctx, fd, &fd->write_closure)) { - kick = 1; - } - } - if (kick) { - maybe_wake_one_watcher_locked(fd); - } - if (fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) { - close_fd_locked(exec_ctx, fd); - } - gpr_mu_unlock(&fd->mu); - - GRPC_FD_UNREF(fd, "poll"); -} - -/******************************************************************************* - * pollset_posix.c - */ - -GPR_TLS_DECL(g_current_thread_poller); -GPR_TLS_DECL(g_current_thread_worker); - -/** The alarm system needs to be able to wakeup 'some poller' sometimes - * (specifically when a new alarm needs to be triggered earlier than the next - * alarm 'epoch'). - * This wakeup_fd gives us something to alert on when such a case occurs. */ -grpc_wakeup_fd grpc_global_wakeup_fd; - -static void remove_worker(grpc_pollset *p, grpc_pollset_worker *worker) { - worker->prev->next = worker->next; - worker->next->prev = worker->prev; -} - -static int pollset_has_workers(grpc_pollset *p) { - return p->root_worker.next != &p->root_worker; -} - -static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) { - if (pollset_has_workers(p)) { - grpc_pollset_worker *w = p->root_worker.next; - remove_worker(p, w); - return w; - } else { - return NULL; - } -} - -static void push_back_worker(grpc_pollset *p, grpc_pollset_worker *worker) { - worker->next = &p->root_worker; - worker->prev = worker->next->prev; - worker->prev->next = worker->next->prev = worker; -} - -static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) { - worker->prev = &p->root_worker; - worker->next = worker->prev->next; - worker->prev->next = worker->next->prev = worker; -} - -static void pollset_kick_ext(grpc_pollset *p, - grpc_pollset_worker *specific_worker, - uint32_t flags) { - GPR_TIMER_BEGIN("pollset_kick_ext", 0); - - /* pollset->mu already held */ - if (specific_worker != NULL) { - if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) { - GPR_TIMER_BEGIN("pollset_kick_ext.broadcast", 0); - GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0); - for (specific_worker = p->root_worker.next; - specific_worker != &p->root_worker; - specific_worker = specific_worker->next) { - grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd); - } - p->kicked_without_pollers = 1; - GPR_TIMER_END("pollset_kick_ext.broadcast", 0); - } else if (gpr_tls_get(&g_current_thread_worker) != - (intptr_t)specific_worker) { - GPR_TIMER_MARK("different_thread_worker", 0); - if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) { - specific_worker->reevaluate_polling_on_wakeup = 1; - } - specific_worker->kicked_specifically = 1; - grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd); - } else if ((flags & GRPC_POLLSET_CAN_KICK_SELF) != 0) { - GPR_TIMER_MARK("kick_yoself", 0); - if ((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) != 0) { - specific_worker->reevaluate_polling_on_wakeup = 1; - } - specific_worker->kicked_specifically = 1; - grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd); - } - } else if (gpr_tls_get(&g_current_thread_poller) != (intptr_t)p) { - GPR_ASSERT((flags & GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) == 0); - GPR_TIMER_MARK("kick_anonymous", 0); - specific_worker = pop_front_worker(p); - if (specific_worker != NULL) { - if (gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) { - /* Prefer not to kick self. Push the worker to the end of the list and - * pop the one from front */ - GPR_TIMER_MARK("kick_anonymous_not_self", 0); - push_back_worker(p, specific_worker); - specific_worker = pop_front_worker(p); - /* If there was only one worker on the pollset, we would get the same - * worker we pushed (the one set on current thread local) back. If so, - * kick it only if GRPC_POLLSET_CAN_KICK_SELF flag is set */ - if ((flags & GRPC_POLLSET_CAN_KICK_SELF) == 0 && - gpr_tls_get(&g_current_thread_worker) == - (intptr_t)specific_worker) { - push_back_worker(p, specific_worker); - specific_worker = NULL; - } - } - if (specific_worker != NULL) { - GPR_TIMER_MARK("finally_kick", 0); - push_back_worker(p, specific_worker); - grpc_wakeup_fd_wakeup(&specific_worker->wakeup_fd->fd); - } - } else { - GPR_TIMER_MARK("kicked_no_pollers", 0); - p->kicked_without_pollers = 1; - } - } - - GPR_TIMER_END("pollset_kick_ext", 0); -} - -static void pollset_kick(grpc_pollset *p, - grpc_pollset_worker *specific_worker) { - pollset_kick_ext(p, specific_worker, 0); -} - -/* global state management */ - -static void pollset_global_init(void) { - gpr_tls_init(&g_current_thread_poller); - gpr_tls_init(&g_current_thread_worker); - grpc_wakeup_fd_init(&grpc_global_wakeup_fd); -} - -static void pollset_global_shutdown(void) { - grpc_wakeup_fd_destroy(&grpc_global_wakeup_fd); - gpr_tls_destroy(&g_current_thread_poller); - gpr_tls_destroy(&g_current_thread_worker); -} - -static void kick_poller(void) { grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); } - -/* main interface */ - -static void become_basic_pollset(grpc_pollset *pollset, grpc_fd *fd_or_null); - -static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { - gpr_mu_init(&pollset->mu); - *mu = &pollset->mu; - pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker; - pollset->in_flight_cbs = 0; - pollset->shutting_down = 0; - pollset->called_shutdown = 0; - pollset->kicked_without_pollers = 0; - pollset->idle_jobs.head = pollset->idle_jobs.tail = NULL; - pollset->local_wakeup_cache = NULL; - pollset->kicked_without_pollers = 0; - become_basic_pollset(pollset, NULL); -} - -static void pollset_destroy(grpc_pollset *pollset) { - GPR_ASSERT(pollset->in_flight_cbs == 0); - GPR_ASSERT(!pollset_has_workers(pollset)); - GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail); - pollset->vtable->destroy(pollset); - while (pollset->local_wakeup_cache) { - grpc_cached_wakeup_fd *next = pollset->local_wakeup_cache->next; - grpc_wakeup_fd_destroy(&pollset->local_wakeup_cache->fd); - gpr_free(pollset->local_wakeup_cache); - pollset->local_wakeup_cache = next; - } - gpr_mu_destroy(&pollset->mu); -} - -static void pollset_reset(grpc_pollset *pollset) { - GPR_ASSERT(pollset->shutting_down); - GPR_ASSERT(pollset->in_flight_cbs == 0); - GPR_ASSERT(!pollset_has_workers(pollset)); - GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail); - pollset->vtable->destroy(pollset); - pollset->shutting_down = 0; - pollset->called_shutdown = 0; - pollset->kicked_without_pollers = 0; - become_basic_pollset(pollset, NULL); -} - -static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_fd *fd) { - gpr_mu_lock(&pollset->mu); - pollset->vtable->add_fd(exec_ctx, pollset, fd, 1); -/* the following (enabled only in debug) will reacquire and then release - our lock - meaning that if the unlocking flag passed to add_fd above is - not respected, the code will deadlock (in a way that we have a chance of - debugging) */ -#ifndef NDEBUG - gpr_mu_lock(&pollset->mu); - gpr_mu_unlock(&pollset->mu); -#endif -} - -static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { - GPR_ASSERT(grpc_closure_list_empty(pollset->idle_jobs)); - pollset->vtable->finish_shutdown(pollset); - grpc_exec_ctx_enqueue(exec_ctx, pollset->shutdown_done, true, NULL); -} - -static void pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_pollset_worker **worker_hdl, gpr_timespec now, - gpr_timespec deadline) { - grpc_pollset_worker worker; - *worker_hdl = &worker; - - /* pollset->mu already held */ - int added_worker = 0; - int locked = 1; - int queued_work = 0; - int keep_polling = 0; - GPR_TIMER_BEGIN("pollset_work", 0); - /* this must happen before we (potentially) drop pollset->mu */ - worker.next = worker.prev = NULL; - worker.reevaluate_polling_on_wakeup = 0; - if (pollset->local_wakeup_cache != NULL) { - worker.wakeup_fd = pollset->local_wakeup_cache; - pollset->local_wakeup_cache = worker.wakeup_fd->next; - } else { - worker.wakeup_fd = gpr_malloc(sizeof(*worker.wakeup_fd)); - grpc_wakeup_fd_init(&worker.wakeup_fd->fd); - } - worker.kicked_specifically = 0; - /* If there's work waiting for the pollset to be idle, and the - pollset is idle, then do that work */ - if (!pollset_has_workers(pollset) && - !grpc_closure_list_empty(pollset->idle_jobs)) { - GPR_TIMER_MARK("pollset_work.idle_jobs", 0); - grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL); - goto done; - } - /* If we're shutting down then we don't execute any extended work */ - if (pollset->shutting_down) { - GPR_TIMER_MARK("pollset_work.shutting_down", 0); - goto done; - } - /* Give do_promote priority so we don't starve it out */ - if (pollset->in_flight_cbs) { - GPR_TIMER_MARK("pollset_work.in_flight_cbs", 0); - gpr_mu_unlock(&pollset->mu); - locked = 0; - goto done; - } - /* Start polling, and keep doing so while we're being asked to - re-evaluate our pollers (this allows poll() based pollers to - ensure they don't miss wakeups) */ - keep_polling = 1; - while (keep_polling) { - keep_polling = 0; - if (!pollset->kicked_without_pollers) { - if (!added_worker) { - push_front_worker(pollset, &worker); - added_worker = 1; - gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker); - } - gpr_tls_set(&g_current_thread_poller, (intptr_t)pollset); - GPR_TIMER_BEGIN("maybe_work_and_unlock", 0); - pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, &worker, - deadline, now); - GPR_TIMER_END("maybe_work_and_unlock", 0); - locked = 0; - gpr_tls_set(&g_current_thread_poller, 0); - } else { - GPR_TIMER_MARK("pollset_work.kicked_without_pollers", 0); - pollset->kicked_without_pollers = 0; - } - /* Finished execution - start cleaning up. - Note that we may arrive here from outside the enclosing while() loop. - In that case we won't loop though as we haven't added worker to the - worker list, which means nobody could ask us to re-evaluate polling). */ - done: - if (!locked) { - queued_work |= grpc_exec_ctx_flush(exec_ctx); - gpr_mu_lock(&pollset->mu); - locked = 1; - } - /* If we're forced to re-evaluate polling (via pollset_kick with - GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) then we land here and force - a loop */ - if (worker.reevaluate_polling_on_wakeup) { - worker.reevaluate_polling_on_wakeup = 0; - pollset->kicked_without_pollers = 0; - if (queued_work || worker.kicked_specifically) { - /* If there's queued work on the list, then set the deadline to be - immediate so we get back out of the polling loop quickly */ - deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC); - } - keep_polling = 1; - } - } - if (added_worker) { - remove_worker(pollset, &worker); - gpr_tls_set(&g_current_thread_worker, 0); - } - /* release wakeup fd to the local pool */ - worker.wakeup_fd->next = pollset->local_wakeup_cache; - pollset->local_wakeup_cache = worker.wakeup_fd; - /* check shutdown conditions */ - if (pollset->shutting_down) { - if (pollset_has_workers(pollset)) { - pollset_kick(pollset, NULL); - } else if (!pollset->called_shutdown && pollset->in_flight_cbs == 0) { - pollset->called_shutdown = 1; - gpr_mu_unlock(&pollset->mu); - finish_shutdown(exec_ctx, pollset); - grpc_exec_ctx_flush(exec_ctx); - /* Continuing to access pollset here is safe -- it is the caller's - * responsibility to not destroy when it has outstanding calls to - * pollset_work. - * TODO(dklempner): Can we refactor the shutdown logic to avoid this? */ - gpr_mu_lock(&pollset->mu); - } else if (!grpc_closure_list_empty(pollset->idle_jobs)) { - grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL); - gpr_mu_unlock(&pollset->mu); - grpc_exec_ctx_flush(exec_ctx); - gpr_mu_lock(&pollset->mu); - } - } - *worker_hdl = NULL; - GPR_TIMER_END("pollset_work", 0); -} - -static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_closure *closure) { - GPR_ASSERT(!pollset->shutting_down); - pollset->shutting_down = 1; - pollset->shutdown_done = closure; - pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); - if (!pollset_has_workers(pollset)) { - grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL); - } - if (!pollset->called_shutdown && pollset->in_flight_cbs == 0 && - !pollset_has_workers(pollset)) { - pollset->called_shutdown = 1; - finish_shutdown(exec_ctx, pollset); - } -} - -static int poll_deadline_to_millis_timeout(gpr_timespec deadline, - gpr_timespec now) { - gpr_timespec timeout; - static const int64_t max_spin_polling_us = 10; - if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) { - return -1; - } - if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros( - max_spin_polling_us, - GPR_TIMESPAN))) <= 0) { - return 0; - } - timeout = gpr_time_sub(deadline, now); - return gpr_time_to_millis(gpr_time_add( - timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN))); -} - -/* - * basic_pollset - a vtable that provides polling for zero or one file - * descriptor via poll() - */ - -typedef struct grpc_unary_promote_args { - const grpc_pollset_vtable *original_vtable; - grpc_pollset *pollset; - grpc_fd *fd; - grpc_closure promotion_closure; -} grpc_unary_promote_args; - -static void basic_do_promote(grpc_exec_ctx *exec_ctx, void *args, - bool success) { - grpc_unary_promote_args *up_args = args; - const grpc_pollset_vtable *original_vtable = up_args->original_vtable; - grpc_pollset *pollset = up_args->pollset; - grpc_fd *fd = up_args->fd; - - /* - * This is quite tricky. There are a number of cases to keep in mind here: - * 1. fd may have been orphaned - * 2. The pollset may no longer be a unary poller (and we can't let case #1 - * leak to other pollset types!) - * 3. pollset's fd (which may have changed) may have been orphaned - * 4. The pollset may be shutting down. - */ - - gpr_mu_lock(&pollset->mu); - /* First we need to ensure that nobody is polling concurrently */ - GPR_ASSERT(!pollset_has_workers(pollset)); - - gpr_free(up_args); - /* At this point the pollset may no longer be a unary poller. In that case - * we should just call the right add function and be done. */ - /* TODO(klempner): If we're not careful this could cause infinite recursion. - * That's not a problem for now because empty_pollset has a trivial poller - * and we don't have any mechanism to unbecome multipoller. */ - pollset->in_flight_cbs--; - if (pollset->shutting_down) { - /* We don't care about this pollset anymore. */ - if (pollset->in_flight_cbs == 0 && !pollset->called_shutdown) { - pollset->called_shutdown = 1; - finish_shutdown(exec_ctx, pollset); - } - } else if (fd_is_orphaned(fd)) { - /* Don't try to add it to anything, we'll drop our ref on it below */ - } else if (pollset->vtable != original_vtable) { - pollset->vtable->add_fd(exec_ctx, pollset, fd, 0); - } else if (fd != pollset->data.ptr) { - grpc_fd *fds[2]; - fds[0] = pollset->data.ptr; - fds[1] = fd; - - if (fds[0] && !fd_is_orphaned(fds[0])) { - platform_become_multipoller(exec_ctx, pollset, fds, GPR_ARRAY_SIZE(fds)); - GRPC_FD_UNREF(fds[0], "basicpoll"); - } else { - /* old fd is orphaned and we haven't cleaned it up until now, so remain a - * unary poller */ - /* Note that it is possible that fds[1] is also orphaned at this point. - * That's okay, we'll correct it at the next add or poll. */ - if (fds[0]) GRPC_FD_UNREF(fds[0], "basicpoll"); - pollset->data.ptr = fd; - GRPC_FD_REF(fd, "basicpoll"); - } - } - - gpr_mu_unlock(&pollset->mu); - - /* Matching ref in basic_pollset_add_fd */ - GRPC_FD_UNREF(fd, "basicpoll_add"); -} - -static void basic_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_fd *fd, int and_unlock_pollset) { - grpc_unary_promote_args *up_args; - GPR_ASSERT(fd); - if (fd == pollset->data.ptr) goto exit; - - if (!pollset_has_workers(pollset)) { - /* Fast path -- no in flight cbs */ - /* TODO(klempner): Comment this out and fix any test failures or establish - * they are due to timing issues */ - grpc_fd *fds[2]; - fds[0] = pollset->data.ptr; - fds[1] = fd; - - if (fds[0] == NULL) { - pollset->data.ptr = fd; - GRPC_FD_REF(fd, "basicpoll"); - } else if (!fd_is_orphaned(fds[0])) { - platform_become_multipoller(exec_ctx, pollset, fds, GPR_ARRAY_SIZE(fds)); - GRPC_FD_UNREF(fds[0], "basicpoll"); - } else { - /* old fd is orphaned and we haven't cleaned it up until now, so remain a - * unary poller */ - GRPC_FD_UNREF(fds[0], "basicpoll"); - pollset->data.ptr = fd; - GRPC_FD_REF(fd, "basicpoll"); - } - goto exit; - } - - /* Now we need to promote. This needs to happen when we're not polling. Since - * this may be called from poll, the wait needs to happen asynchronously. */ - GRPC_FD_REF(fd, "basicpoll_add"); - pollset->in_flight_cbs++; - up_args = gpr_malloc(sizeof(*up_args)); - up_args->fd = fd; - up_args->original_vtable = pollset->vtable; - up_args->pollset = pollset; - up_args->promotion_closure.cb = basic_do_promote; - up_args->promotion_closure.cb_arg = up_args; - - grpc_closure_list_add(&pollset->idle_jobs, &up_args->promotion_closure, 1); - pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); - -exit: - if (and_unlock_pollset) { - gpr_mu_unlock(&pollset->mu); - } -} - -static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, - grpc_pollset_worker *worker, - gpr_timespec deadline, - gpr_timespec now) { -#define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR) -#define POLLIN_CHECK (POLLIN | POLLHUP | POLLERR) - - struct pollfd pfd[3]; - grpc_fd *fd; - grpc_fd_watcher fd_watcher; - int timeout; - int r; - nfds_t nfds; - - fd = pollset->data.ptr; - if (fd && fd_is_orphaned(fd)) { - GRPC_FD_UNREF(fd, "basicpoll"); - fd = pollset->data.ptr = NULL; - } - timeout = poll_deadline_to_millis_timeout(deadline, now); - pfd[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd); - pfd[0].events = POLLIN; - pfd[0].revents = 0; - pfd[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd->fd); - pfd[1].events = POLLIN; - pfd[1].revents = 0; - nfds = 2; - if (fd) { - pfd[2].fd = fd->fd; - pfd[2].revents = 0; - GRPC_FD_REF(fd, "basicpoll_begin"); - gpr_mu_unlock(&pollset->mu); - pfd[2].events = - (short)fd_begin_poll(fd, pollset, worker, POLLIN, POLLOUT, &fd_watcher); - if (pfd[2].events != 0) { - nfds++; - } - } else { - gpr_mu_unlock(&pollset->mu); - } - - /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid - even going into the blocking annotation if possible */ - /* poll fd count (argument 2) is shortened by one if we have no events - to poll on - such that it only includes the kicker */ - GPR_TIMER_BEGIN("poll", 0); - GRPC_SCHEDULING_START_BLOCKING_REGION; - r = grpc_poll_function(pfd, nfds, timeout); - GRPC_SCHEDULING_END_BLOCKING_REGION; - GPR_TIMER_END("poll", 0); - - if (r < 0) { - if (errno != EINTR) { - gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); - } - if (fd) { - fd_end_poll(exec_ctx, &fd_watcher, 0, 0, NULL); - } - } else if (r == 0) { - if (fd) { - fd_end_poll(exec_ctx, &fd_watcher, 0, 0, NULL); - } - } else { - if (pfd[0].revents & POLLIN_CHECK) { - grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd); - } - if (pfd[1].revents & POLLIN_CHECK) { - grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd); - } - if (nfds > 2) { - fd_end_poll(exec_ctx, &fd_watcher, pfd[2].revents & POLLIN_CHECK, - pfd[2].revents & POLLOUT_CHECK, pollset); - } else if (fd) { - fd_end_poll(exec_ctx, &fd_watcher, 0, 0, NULL); - } - } - - if (fd) { - GRPC_FD_UNREF(fd, "basicpoll_begin"); - } -} - -static void basic_pollset_destroy(grpc_pollset *pollset) { - if (pollset->data.ptr != NULL) { - GRPC_FD_UNREF(pollset->data.ptr, "basicpoll"); - pollset->data.ptr = NULL; - } -} - -static const grpc_pollset_vtable basic_pollset = { - basic_pollset_add_fd, basic_pollset_maybe_work_and_unlock, - basic_pollset_destroy, basic_pollset_destroy}; - -static void become_basic_pollset(grpc_pollset *pollset, grpc_fd *fd_or_null) { - pollset->vtable = &basic_pollset; - pollset->data.ptr = fd_or_null; - if (fd_or_null != NULL) { - GRPC_FD_REF(fd_or_null, "basicpoll"); - } -} - -/******************************************************************************* - * pollset_multipoller_with_poll_posix.c - */ - -#ifndef GPR_LINUX_MULTIPOLL_WITH_EPOLL - -typedef struct { - /* all polled fds */ - size_t fd_count; - size_t fd_capacity; - grpc_fd **fds; - /* fds that have been removed from the pollset explicitly */ - size_t del_count; - size_t del_capacity; - grpc_fd **dels; -} poll_hdr; - -static void multipoll_with_poll_pollset_add_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, - grpc_fd *fd, - int and_unlock_pollset) { - size_t i; - poll_hdr *h = pollset->data.ptr; - /* TODO(ctiller): this is O(num_fds^2); maybe switch to a hash set here */ - for (i = 0; i < h->fd_count; i++) { - if (h->fds[i] == fd) goto exit; - } - if (h->fd_count == h->fd_capacity) { - h->fd_capacity = GPR_MAX(h->fd_capacity + 8, h->fd_count * 3 / 2); - h->fds = gpr_realloc(h->fds, sizeof(grpc_fd *) * h->fd_capacity); - } - h->fds[h->fd_count++] = fd; - GRPC_FD_REF(fd, "multipoller"); -exit: - if (and_unlock_pollset) { - gpr_mu_unlock(&pollset->mu); - } -} - -static void multipoll_with_poll_pollset_maybe_work_and_unlock( - grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker, - gpr_timespec deadline, gpr_timespec now) { -#define POLLOUT_CHECK (POLLOUT | POLLHUP | POLLERR) -#define POLLIN_CHECK (POLLIN | POLLHUP | POLLERR) - - int timeout; - int r; - size_t i, j, fd_count; - nfds_t pfd_count; - poll_hdr *h; - /* TODO(ctiller): inline some elements to avoid an allocation */ - grpc_fd_watcher *watchers; - struct pollfd *pfds; - - h = pollset->data.ptr; - timeout = poll_deadline_to_millis_timeout(deadline, now); - /* TODO(ctiller): perform just one malloc here if we exceed the inline case */ - pfds = gpr_malloc(sizeof(*pfds) * (h->fd_count + 2)); - watchers = gpr_malloc(sizeof(*watchers) * (h->fd_count + 2)); - fd_count = 0; - pfd_count = 2; - pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd); - pfds[0].events = POLLIN; - pfds[0].revents = 0; - pfds[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd->fd); - pfds[1].events = POLLIN; - pfds[1].revents = 0; - for (i = 0; i < h->fd_count; i++) { - int remove = fd_is_orphaned(h->fds[i]); - for (j = 0; !remove && j < h->del_count; j++) { - if (h->fds[i] == h->dels[j]) remove = 1; - } - if (remove) { - GRPC_FD_UNREF(h->fds[i], "multipoller"); - } else { - h->fds[fd_count++] = h->fds[i]; - watchers[pfd_count].fd = h->fds[i]; - GRPC_FD_REF(watchers[pfd_count].fd, "multipoller_start"); - pfds[pfd_count].fd = h->fds[i]->fd; - pfds[pfd_count].revents = 0; - pfd_count++; - } - } - for (j = 0; j < h->del_count; j++) { - GRPC_FD_UNREF(h->dels[j], "multipoller_del"); - } - h->del_count = 0; - h->fd_count = fd_count; - gpr_mu_unlock(&pollset->mu); - - for (i = 2; i < pfd_count; i++) { - grpc_fd *fd = watchers[i].fd; - pfds[i].events = (short)fd_begin_poll(fd, pollset, worker, POLLIN, POLLOUT, - &watchers[i]); - GRPC_FD_UNREF(fd, "multipoller_start"); - } - - /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid - even going into the blocking annotation if possible */ - GRPC_SCHEDULING_START_BLOCKING_REGION; - r = grpc_poll_function(pfds, pfd_count, timeout); - GRPC_SCHEDULING_END_BLOCKING_REGION; - - if (r < 0) { - if (errno != EINTR) { - gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); - } - for (i = 2; i < pfd_count; i++) { - fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL); - } - } else if (r == 0) { - for (i = 2; i < pfd_count; i++) { - fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL); - } - } else { - if (pfds[0].revents & POLLIN_CHECK) { - grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd); - } - if (pfds[1].revents & POLLIN_CHECK) { - grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd); - } - for (i = 2; i < pfd_count; i++) { - if (watchers[i].fd == NULL) { - fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL); - continue; - } - fd_end_poll(exec_ctx, &watchers[i], pfds[i].revents & POLLIN_CHECK, - pfds[i].revents & POLLOUT_CHECK, pollset); - } - } - - gpr_free(pfds); - gpr_free(watchers); -} - -static void multipoll_with_poll_pollset_finish_shutdown(grpc_pollset *pollset) { - size_t i; - poll_hdr *h = pollset->data.ptr; - for (i = 0; i < h->fd_count; i++) { - GRPC_FD_UNREF(h->fds[i], "multipoller"); - } - for (i = 0; i < h->del_count; i++) { - GRPC_FD_UNREF(h->dels[i], "multipoller_del"); - } - h->fd_count = 0; - h->del_count = 0; -} - -static void multipoll_with_poll_pollset_destroy(grpc_pollset *pollset) { - poll_hdr *h = pollset->data.ptr; - multipoll_with_poll_pollset_finish_shutdown(pollset); - gpr_free(h->fds); - gpr_free(h->dels); - gpr_free(h); -} - -static const grpc_pollset_vtable multipoll_with_poll_pollset = { - multipoll_with_poll_pollset_add_fd, - multipoll_with_poll_pollset_maybe_work_and_unlock, - multipoll_with_poll_pollset_finish_shutdown, - multipoll_with_poll_pollset_destroy}; - -static void poll_become_multipoller(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, grpc_fd **fds, - size_t nfds) { - size_t i; - poll_hdr *h = gpr_malloc(sizeof(poll_hdr)); - pollset->vtable = &multipoll_with_poll_pollset; - pollset->data.ptr = h; - h->fd_count = nfds; - h->fd_capacity = nfds; - h->fds = gpr_malloc(nfds * sizeof(grpc_fd *)); - h->del_count = 0; - h->del_capacity = 0; - h->dels = NULL; - for (i = 0; i < nfds; i++) { - h->fds[i] = fds[i]; - GRPC_FD_REF(fds[i], "multipoller"); - } -} - -#endif /* !GPR_LINUX_MULTIPOLL_WITH_EPOLL */ - -/******************************************************************************* - * pollset_multipoller_with_epoll_posix.c - */ - -#ifdef GPR_LINUX_MULTIPOLL_WITH_EPOLL - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "src/core/lib/iomgr/ev_posix.h" -#include "src/core/lib/profiling/timers.h" -#include "src/core/lib/support/block_annotate.h" - -static void set_ready(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure **st, - grpc_pollset *read_notifier_pollset) { - /* only one set_ready can be active at once (but there may be a racing - notify_on) */ - gpr_mu_lock(&fd->mu); - set_ready_locked(exec_ctx, fd, st); - - /* A non-NULL read_notifier_pollset means that the fd is readable. */ - if (read_notifier_pollset != NULL) { - /* Note: Since the fd might be a part of multiple pollsets, this might be - * called multiple times (for each time the fd becomes readable) and it is - * okay to set the fd's read-notifier pollset to anyone of these pollsets */ - set_read_notifier_pollset_locked(exec_ctx, fd, read_notifier_pollset); - } - - gpr_mu_unlock(&fd->mu); -} - -static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, - grpc_pollset *notifier_pollset) { - set_ready(exec_ctx, fd, &fd->read_closure, notifier_pollset); -} - -static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { - set_ready(exec_ctx, fd, &fd->write_closure, NULL); -} - -struct epoll_fd_list { - int *epoll_fds; - size_t count; - size_t capacity; -}; - -static struct epoll_fd_list epoll_fd_global_list; -static gpr_once init_epoll_fd_list_mu = GPR_ONCE_INIT; -static gpr_mu epoll_fd_list_mu; - -static void init_mu(void) { gpr_mu_init(&epoll_fd_list_mu); } - -static void add_epoll_fd_to_global_list(int epoll_fd) { - gpr_once_init(&init_epoll_fd_list_mu, init_mu); - - gpr_mu_lock(&epoll_fd_list_mu); - if (epoll_fd_global_list.count == epoll_fd_global_list.capacity) { - epoll_fd_global_list.capacity = - GPR_MAX((size_t)8, epoll_fd_global_list.capacity * 2); - epoll_fd_global_list.epoll_fds = - gpr_realloc(epoll_fd_global_list.epoll_fds, - epoll_fd_global_list.capacity * sizeof(int)); - } - epoll_fd_global_list.epoll_fds[epoll_fd_global_list.count++] = epoll_fd; - gpr_mu_unlock(&epoll_fd_list_mu); -} - -static void remove_epoll_fd_from_global_list(int epoll_fd) { - gpr_mu_lock(&epoll_fd_list_mu); - GPR_ASSERT(epoll_fd_global_list.count > 0); - for (size_t i = 0; i < epoll_fd_global_list.count; i++) { - if (epoll_fd == epoll_fd_global_list.epoll_fds[i]) { - epoll_fd_global_list.epoll_fds[i] = - epoll_fd_global_list.epoll_fds[--(epoll_fd_global_list.count)]; - break; - } - } - gpr_mu_unlock(&epoll_fd_list_mu); -} - -static void remove_fd_from_all_epoll_sets(int fd) { - int err; - gpr_once_init(&init_epoll_fd_list_mu, init_mu); - gpr_mu_lock(&epoll_fd_list_mu); - if (epoll_fd_global_list.count == 0) { - gpr_mu_unlock(&epoll_fd_list_mu); - return; - } - for (size_t i = 0; i < epoll_fd_global_list.count; i++) { - err = epoll_ctl(epoll_fd_global_list.epoll_fds[i], EPOLL_CTL_DEL, fd, NULL); - if (err < 0 && errno != ENOENT) { - gpr_log(GPR_ERROR, "epoll_ctl del for %d failed: %s", fd, - strerror(errno)); - } - } - gpr_mu_unlock(&epoll_fd_list_mu); -} - -typedef struct { - grpc_pollset *pollset; - grpc_fd *fd; - grpc_closure closure; -} delayed_add; - -typedef struct { int epoll_fd; } epoll_hdr; - -static void finally_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, - grpc_fd *fd) { - epoll_hdr *h = pollset->data.ptr; - struct epoll_event ev; - int err; - grpc_fd_watcher watcher; - - /* We pretend to be polling whilst adding an fd to keep the fd from being - closed during the add. This may result in a spurious wakeup being assigned - to this pollset whilst adding, but that should be benign. */ - GPR_ASSERT(fd_begin_poll(fd, pollset, NULL, 0, 0, &watcher) == 0); - if (watcher.fd != NULL) { - ev.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET); - ev.data.ptr = fd; - err = epoll_ctl(h->epoll_fd, EPOLL_CTL_ADD, fd->fd, &ev); - if (err < 0) { - /* FDs may be added to a pollset multiple times, so EEXIST is normal. */ - if (errno != EEXIST) { - gpr_log(GPR_ERROR, "epoll_ctl add for %d failed: %s", fd->fd, - strerror(errno)); - } - } - } - fd_end_poll(exec_ctx, &watcher, 0, 0, NULL); -} - -static void perform_delayed_add(grpc_exec_ctx *exec_ctx, void *arg, - bool iomgr_status) { - delayed_add *da = arg; - - if (!fd_is_orphaned(da->fd)) { - finally_add_fd(exec_ctx, da->pollset, da->fd); - } - - gpr_mu_lock(&da->pollset->mu); - da->pollset->in_flight_cbs--; - if (da->pollset->shutting_down) { - /* We don't care about this pollset anymore. */ - if (da->pollset->in_flight_cbs == 0 && !da->pollset->called_shutdown) { - da->pollset->called_shutdown = 1; - grpc_exec_ctx_enqueue(exec_ctx, da->pollset->shutdown_done, true, NULL); - } - } - gpr_mu_unlock(&da->pollset->mu); - - GRPC_FD_UNREF(da->fd, "delayed_add"); - - gpr_free(da); -} - -static void multipoll_with_epoll_pollset_add_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, - grpc_fd *fd, - int and_unlock_pollset) { - if (and_unlock_pollset) { - gpr_mu_unlock(&pollset->mu); - finally_add_fd(exec_ctx, pollset, fd); - } else { - delayed_add *da = gpr_malloc(sizeof(*da)); - da->pollset = pollset; - da->fd = fd; - GRPC_FD_REF(fd, "delayed_add"); - grpc_closure_init(&da->closure, perform_delayed_add, da); - pollset->in_flight_cbs++; - grpc_exec_ctx_enqueue(exec_ctx, &da->closure, true, NULL); - } -} - -/* TODO(klempner): We probably want to turn this down a bit */ -#define GRPC_EPOLL_MAX_EVENTS 1000 - -static void multipoll_with_epoll_pollset_maybe_work_and_unlock( - grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker, - gpr_timespec deadline, gpr_timespec now) { - struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS]; - int ep_rv; - int poll_rv; - epoll_hdr *h = pollset->data.ptr; - int timeout_ms; - struct pollfd pfds[2]; - - /* If you want to ignore epoll's ability to sanely handle parallel pollers, - * for a more apples-to-apples performance comparison with poll, add a - * if (pollset->counter != 0) { return 0; } - * here. - */ - - gpr_mu_unlock(&pollset->mu); - - timeout_ms = poll_deadline_to_millis_timeout(deadline, now); - - pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker->wakeup_fd->fd); - pfds[0].events = POLLIN; - pfds[0].revents = 0; - pfds[1].fd = h->epoll_fd; - pfds[1].events = POLLIN; - pfds[1].revents = 0; - - /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid - even going into the blocking annotation if possible */ - GPR_TIMER_BEGIN("poll", 0); - GRPC_SCHEDULING_START_BLOCKING_REGION; - poll_rv = grpc_poll_function(pfds, 2, timeout_ms); - GRPC_SCHEDULING_END_BLOCKING_REGION; - GPR_TIMER_END("poll", 0); - - if (poll_rv < 0) { - if (errno != EINTR) { - gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno)); - } - } else if (poll_rv == 0) { - /* do nothing */ - } else { - if (pfds[0].revents) { - grpc_wakeup_fd_consume_wakeup(&worker->wakeup_fd->fd); - } - if (pfds[1].revents) { - do { - /* The following epoll_wait never blocks; it has a timeout of 0 */ - ep_rv = epoll_wait(h->epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, 0); - if (ep_rv < 0) { - if (errno != EINTR) { - gpr_log(GPR_ERROR, "epoll_wait() failed: %s", strerror(errno)); - } - } else { - int i; - for (i = 0; i < ep_rv; ++i) { - grpc_fd *fd = ep_ev[i].data.ptr; - /* TODO(klempner): We might want to consider making err and pri - * separate events */ - int cancel = ep_ev[i].events & (EPOLLERR | EPOLLHUP); - int read_ev = ep_ev[i].events & (EPOLLIN | EPOLLPRI); - int write_ev = ep_ev[i].events & EPOLLOUT; - if (fd == NULL) { - grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd); - } else { - if (read_ev || cancel) { - fd_become_readable(exec_ctx, fd, pollset); - } - if (write_ev || cancel) { - fd_become_writable(exec_ctx, fd); - } - } - } - } - } while (ep_rv == GRPC_EPOLL_MAX_EVENTS); - } - } -} - -static void multipoll_with_epoll_pollset_finish_shutdown( - grpc_pollset *pollset) {} - -static void multipoll_with_epoll_pollset_destroy(grpc_pollset *pollset) { - epoll_hdr *h = pollset->data.ptr; - close(h->epoll_fd); - remove_epoll_fd_from_global_list(h->epoll_fd); - gpr_free(h); -} - -static const grpc_pollset_vtable multipoll_with_epoll_pollset = { - multipoll_with_epoll_pollset_add_fd, - multipoll_with_epoll_pollset_maybe_work_and_unlock, - multipoll_with_epoll_pollset_finish_shutdown, - multipoll_with_epoll_pollset_destroy}; - -static void epoll_become_multipoller(grpc_exec_ctx *exec_ctx, - grpc_pollset *pollset, grpc_fd **fds, - size_t nfds) { - size_t i; - epoll_hdr *h = gpr_malloc(sizeof(epoll_hdr)); - struct epoll_event ev; - int err; - - pollset->vtable = &multipoll_with_epoll_pollset; - pollset->data.ptr = h; - h->epoll_fd = epoll_create1(EPOLL_CLOEXEC); - if (h->epoll_fd < 0) { - /* TODO(klempner): Fall back to poll here, especially on ENOSYS */ - gpr_log(GPR_ERROR, "epoll_create1 failed: %s", strerror(errno)); - abort(); - } - add_epoll_fd_to_global_list(h->epoll_fd); - - ev.events = (uint32_t)(EPOLLIN | EPOLLET); - ev.data.ptr = NULL; - err = epoll_ctl(h->epoll_fd, EPOLL_CTL_ADD, - GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd), &ev); - if (err < 0) { - gpr_log(GPR_ERROR, "epoll_ctl add for %d failed: %s", - GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd), - strerror(errno)); - } - - for (i = 0; i < nfds; i++) { - multipoll_with_epoll_pollset_add_fd(exec_ctx, pollset, fds[i], 0); - } -} - -#else /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */ - -static void remove_fd_from_all_epoll_sets(int fd) {} - -#endif /* GPR_LINUX_MULTIPOLL_WITH_EPOLL */ - -/******************************************************************************* - * pollset_set_posix.c - */ - -static grpc_pollset_set *pollset_set_create(void) { - grpc_pollset_set *pollset_set = gpr_malloc(sizeof(*pollset_set)); - memset(pollset_set, 0, sizeof(*pollset_set)); - gpr_mu_init(&pollset_set->mu); - return pollset_set; -} - -static void pollset_set_destroy(grpc_pollset_set *pollset_set) { - size_t i; - gpr_mu_destroy(&pollset_set->mu); - for (i = 0; i < pollset_set->fd_count; i++) { - GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); - } - gpr_free(pollset_set->pollsets); - gpr_free(pollset_set->pollset_sets); - gpr_free(pollset_set->fds); - gpr_free(pollset_set); -} - -static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, - grpc_pollset *pollset) { - size_t i, j; - gpr_mu_lock(&pollset_set->mu); - if (pollset_set->pollset_count == pollset_set->pollset_capacity) { - pollset_set->pollset_capacity = - GPR_MAX(8, 2 * pollset_set->pollset_capacity); - pollset_set->pollsets = - gpr_realloc(pollset_set->pollsets, pollset_set->pollset_capacity * - sizeof(*pollset_set->pollsets)); - } - pollset_set->pollsets[pollset_set->pollset_count++] = pollset; - for (i = 0, j = 0; i < pollset_set->fd_count; i++) { - if (fd_is_orphaned(pollset_set->fds[i])) { - GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set"); - } else { - pollset_add_fd(exec_ctx, pollset, pollset_set->fds[i]); - pollset_set->fds[j++] = pollset_set->fds[i]; - } - } - pollset_set->fd_count = j; - gpr_mu_unlock(&pollset_set->mu); -} - -static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, - grpc_pollset *pollset) { - size_t i; - gpr_mu_lock(&pollset_set->mu); - for (i = 0; i < pollset_set->pollset_count; i++) { - if (pollset_set->pollsets[i] == pollset) { - pollset_set->pollset_count--; - GPR_SWAP(grpc_pollset *, pollset_set->pollsets[i], - pollset_set->pollsets[pollset_set->pollset_count]); - break; - } - } - gpr_mu_unlock(&pollset_set->mu); -} - -static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *bag, - grpc_pollset_set *item) { - size_t i, j; - gpr_mu_lock(&bag->mu); - if (bag->pollset_set_count == bag->pollset_set_capacity) { - bag->pollset_set_capacity = GPR_MAX(8, 2 * bag->pollset_set_capacity); - bag->pollset_sets = - gpr_realloc(bag->pollset_sets, - bag->pollset_set_capacity * sizeof(*bag->pollset_sets)); - } - bag->pollset_sets[bag->pollset_set_count++] = item; - for (i = 0, j = 0; i < bag->fd_count; i++) { - if (fd_is_orphaned(bag->fds[i])) { - GRPC_FD_UNREF(bag->fds[i], "pollset_set"); - } else { - pollset_set_add_fd(exec_ctx, item, bag->fds[i]); - bag->fds[j++] = bag->fds[i]; - } - } - bag->fd_count = j; - gpr_mu_unlock(&bag->mu); -} - -static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *bag, - grpc_pollset_set *item) { - size_t i; - gpr_mu_lock(&bag->mu); - for (i = 0; i < bag->pollset_set_count; i++) { - if (bag->pollset_sets[i] == item) { - bag->pollset_set_count--; - GPR_SWAP(grpc_pollset_set *, bag->pollset_sets[i], - bag->pollset_sets[bag->pollset_set_count]); - break; - } - } - gpr_mu_unlock(&bag->mu); -} - -static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, grpc_fd *fd) { - size_t i; - gpr_mu_lock(&pollset_set->mu); - if (pollset_set->fd_count == pollset_set->fd_capacity) { - pollset_set->fd_capacity = GPR_MAX(8, 2 * pollset_set->fd_capacity); - pollset_set->fds = gpr_realloc( - pollset_set->fds, pollset_set->fd_capacity * sizeof(*pollset_set->fds)); - } - GRPC_FD_REF(fd, "pollset_set"); - pollset_set->fds[pollset_set->fd_count++] = fd; - for (i = 0; i < pollset_set->pollset_count; i++) { - pollset_add_fd(exec_ctx, pollset_set->pollsets[i], fd); - } - for (i = 0; i < pollset_set->pollset_set_count; i++) { - pollset_set_add_fd(exec_ctx, pollset_set->pollset_sets[i], fd); - } - gpr_mu_unlock(&pollset_set->mu); -} - -static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, - grpc_pollset_set *pollset_set, grpc_fd *fd) { - size_t i; - gpr_mu_lock(&pollset_set->mu); - for (i = 0; i < pollset_set->fd_count; i++) { - if (pollset_set->fds[i] == fd) { - pollset_set->fd_count--; - GPR_SWAP(grpc_fd *, pollset_set->fds[i], - pollset_set->fds[pollset_set->fd_count]); - GRPC_FD_UNREF(fd, "pollset_set"); - break; - } - } - for (i = 0; i < pollset_set->pollset_set_count; i++) { - pollset_set_del_fd(exec_ctx, pollset_set->pollset_sets[i], fd); - } - gpr_mu_unlock(&pollset_set->mu); -} - -/******************************************************************************* - * event engine binding - */ - -static void shutdown_engine(void) { - fd_global_shutdown(); - pollset_global_shutdown(); -} - -static const grpc_event_engine_vtable vtable = { - .pollset_size = sizeof(grpc_pollset), - - .fd_create = fd_create, - .fd_wrapped_fd = fd_wrapped_fd, - .fd_orphan = fd_orphan, - .fd_shutdown = fd_shutdown, - .fd_notify_on_read = fd_notify_on_read, - .fd_notify_on_write = fd_notify_on_write, - .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset, - - .pollset_init = pollset_init, - .pollset_shutdown = pollset_shutdown, - .pollset_reset = pollset_reset, - .pollset_destroy = pollset_destroy, - .pollset_work = pollset_work, - .pollset_kick = pollset_kick, - .pollset_add_fd = pollset_add_fd, - - .pollset_set_create = pollset_set_create, - .pollset_set_destroy = pollset_set_destroy, - .pollset_set_add_pollset = pollset_set_add_pollset, - .pollset_set_del_pollset = pollset_set_del_pollset, - .pollset_set_add_pollset_set = pollset_set_add_pollset_set, - .pollset_set_del_pollset_set = pollset_set_del_pollset_set, - .pollset_set_add_fd = pollset_set_add_fd, - .pollset_set_del_fd = pollset_set_del_fd, - - .kick_poller = kick_poller, - - .shutdown_engine = shutdown_engine, -}; - -const grpc_event_engine_vtable *grpc_init_poll_and_epoll_posix(void) { -#ifdef GPR_LINUX_MULTIPOLL_WITH_EPOLL - platform_become_multipoller = epoll_become_multipoller; -#else - platform_become_multipoller = poll_become_multipoller; -#endif - fd_global_init(); - pollset_global_init(); - return &vtable; -} - -#endif diff --git a/src/core/lib/iomgr/ev_poll_and_epoll_posix.h b/src/core/lib/iomgr/ev_poll_and_epoll_posix.h deleted file mode 100644 index 06d6dbf29d..0000000000 --- a/src/core/lib/iomgr/ev_poll_and_epoll_posix.h +++ /dev/null @@ -1,41 +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. - * - */ - -#ifndef GRPC_CORE_LIB_IOMGR_EV_POLL_AND_EPOLL_POSIX_H -#define GRPC_CORE_LIB_IOMGR_EV_POLL_AND_EPOLL_POSIX_H - -#include "src/core/lib/iomgr/ev_posix.h" - -const grpc_event_engine_vtable *grpc_init_poll_and_epoll_posix(void); - -#endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_AND_EPOLL_POSIX_H */ diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c index fafb3b4b6f..4d2ec5eb98 100644 --- a/src/core/lib/iomgr/ev_poll_posix.c +++ b/src/core/lib/iomgr/ev_poll_posix.c @@ -59,6 +59,8 @@ * FD declarations */ +grpc_wakeup_fd grpc_global_wakeup_fd; + typedef struct grpc_fd_watcher { struct grpc_fd_watcher *next; struct grpc_fd_watcher *prev; diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c index 6477b05dcd..95520b01d3 100644 --- a/src/core/lib/iomgr/ev_posix.c +++ b/src/core/lib/iomgr/ev_posix.c @@ -44,7 +44,6 @@ #include #include -#include "src/core/lib/iomgr/ev_poll_and_epoll_posix.h" #include "src/core/lib/iomgr/ev_poll_posix.h" #include "src/core/lib/support/env.h" @@ -62,7 +61,7 @@ typedef struct { } event_engine_factory; static const event_engine_factory g_factories[] = { - {"poll", grpc_init_poll_posix}, {"legacy", grpc_init_poll_and_epoll_posix}, + {"poll", grpc_init_poll_posix}, }; static void add(const char *beg, const char *end, char ***ss, size_t *ns) { diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 162191b06d..aa79c8c2a8 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -94,7 +94,6 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', - 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', diff --git a/third_party/protobuf b/third_party/protobuf index 3470b6895a..a1938b2aa9 160000 --- a/third_party/protobuf +++ b/third_party/protobuf @@ -1 +1 @@ -Subproject commit 3470b6895aa659b7559ed678e029a5338e535f14 +Subproject commit a1938b2aa9ca86ce7ce50c27ff9737c1008d2a03 diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 212dfc3160..5afed4201a 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -807,7 +807,6 @@ src/core/lib/http/parser.h \ src/core/lib/iomgr/closure.h \ src/core/lib/iomgr/endpoint.h \ src/core/lib/iomgr/endpoint_pair.h \ -src/core/lib/iomgr/ev_poll_and_epoll_posix.h \ src/core/lib/iomgr/ev_poll_posix.h \ src/core/lib/iomgr/ev_posix.h \ src/core/lib/iomgr/exec_ctx.h \ @@ -946,7 +945,6 @@ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ -src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 5f0943b440..0538dce419 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -157,7 +157,7 @@ class CLanguage(object): 'windows': ['all'], 'mac': ['all'], 'posix': ['all'], - 'linux': ['poll'], # DISABLED DUE TO BUGS: 'legacy' + 'linux': ['poll'], } for target in binaries: polling_strategies = (POLLING_STRATEGIES[self.platform] diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 3866ebb0e5..64a49f5f76 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -5645,7 +5645,6 @@ "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", - "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -5745,8 +5744,6 @@ "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", - "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", - "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.c", diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index a20d386fa3..2dba1de384 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -316,7 +316,6 @@ - @@ -475,8 +474,6 @@ - - diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index d5465176a2..1c78919370 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -55,9 +55,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr @@ -653,9 +650,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 09748f082c..90ad80f2fc 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -304,7 +304,6 @@ - @@ -450,8 +449,6 @@ - - diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index a85bfeefe6..2b19c0fb34 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -58,9 +58,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr @@ -575,9 +572,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr -- cgit v1.2.3 From 29f2cb868741967ed34fcb293451784f7effe2d8 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Sat, 21 May 2016 13:55:03 +0000 Subject: Add a Cython-level cancel-many-calls test --- src/python/grpcio/tests/tests.json | 1 + .../tests/unit/_cython/_cancel_many_calls_test.py | 222 +++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 src/python/grpcio/tests/unit/_cython/_cancel_many_calls_test.py (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/tests/tests.json b/src/python/grpcio/tests/tests.json index 691062f25a..1beb619f87 100644 --- a/src/python/grpcio/tests/tests.json +++ b/src/python/grpcio/tests/tests.json @@ -5,6 +5,7 @@ "_base_interface_test.SyncPeasyTest", "_beta_features_test.BetaFeaturesTest", "_beta_features_test.ContextManagementAndLifecycleTest", + "_cancel_many_calls_test.CancelManyCallsTest", "_channel_test.ChannelTest", "_connectivity_channel_test.ChannelConnectivityTest", "_core_over_links_base_interface_test.AsyncEasyTest", diff --git a/src/python/grpcio/tests/unit/_cython/_cancel_many_calls_test.py b/src/python/grpcio/tests/unit/_cython/_cancel_many_calls_test.py new file mode 100644 index 0000000000..c1de779014 --- /dev/null +++ b/src/python/grpcio/tests/unit/_cython/_cancel_many_calls_test.py @@ -0,0 +1,222 @@ +# Copyright 2016, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Test making many calls and immediately cancelling most of them.""" + +import threading +import unittest + +from grpc._cython import cygrpc +from grpc.framework.foundation import logging_pool +from tests.unit.framework.common import test_constants + +_INFINITE_FUTURE = cygrpc.Timespec(float('+inf')) +_EMPTY_FLAGS = 0 +_EMPTY_METADATA = cygrpc.Metadata(()) + +_SERVER_SHUTDOWN_TAG = 'server_shutdown' +_REQUEST_CALL_TAG = 'request_call' +_RECEIVE_CLOSE_ON_SERVER_TAG = 'receive_close_on_server' +_RECEIVE_MESSAGE_TAG = 'receive_message' +_SERVER_COMPLETE_CALL_TAG = 'server_complete_call' + +_SUCCESS_CALL_FRACTION = 1.0 / 8.0 + + +class _State(object): + + def __init__(self): + self.condition = threading.Condition() + self.handlers_released = False + self.parked_handlers = 0 + self.handled_rpcs = 0 + + +def _is_cancellation_event(event): + return ( + event.tag is _RECEIVE_CLOSE_ON_SERVER_TAG and + event.batch_operations[0].received_cancelled) + + +class _Handler(object): + + def __init__(self, state, completion_queue, rpc_event): + self._state = state + self._lock = threading.Lock() + self._completion_queue = completion_queue + self._call = rpc_event.operation_call + + def __call__(self): + with self._state.condition: + self._state.parked_handlers += 1 + if self._state.parked_handlers == test_constants.THREAD_CONCURRENCY: + self._state.condition.notify_all() + while not self._state.handlers_released: + self._state.condition.wait() + + with self._lock: + self._call.start_batch( + cygrpc.Operations( + (cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),)), + _RECEIVE_CLOSE_ON_SERVER_TAG) + self._call.start_batch( + cygrpc.Operations((cygrpc.operation_receive_message(_EMPTY_FLAGS),)), + _RECEIVE_MESSAGE_TAG) + first_event = self._completion_queue.poll() + if _is_cancellation_event(first_event): + self._completion_queue.poll() + else: + with self._lock: + operations = ( + cygrpc.operation_send_initial_metadata( + _EMPTY_METADATA, _EMPTY_FLAGS), + cygrpc.operation_send_message(b'\x79\x57', _EMPTY_FLAGS), + cygrpc.operation_send_status_from_server( + _EMPTY_METADATA, cygrpc.StatusCode.ok, b'test details!', + _EMPTY_FLAGS), + ) + self._call.start_batch( + cygrpc.Operations(operations), _SERVER_COMPLETE_CALL_TAG) + self._completion_queue.poll() + self._completion_queue.poll() + + +def _serve(state, server, server_completion_queue, thread_pool): + for _ in range(test_constants.RPC_CONCURRENCY): + call_completion_queue = cygrpc.CompletionQueue() + server.request_call( + call_completion_queue, server_completion_queue, _REQUEST_CALL_TAG) + rpc_event = server_completion_queue.poll() + thread_pool.submit(_Handler(state, call_completion_queue, rpc_event)) + with state.condition: + state.handled_rpcs += 1 + if test_constants.RPC_CONCURRENCY <= state.handled_rpcs: + state.condition.notify_all() + server_completion_queue.poll() + + +class _QueueDriver(object): + + def __init__(self, condition, completion_queue, due): + self._condition = condition + self._completion_queue = completion_queue + self._due = due + self._events = [] + self._returned = False + + def start(self): + def in_thread(): + while True: + event = self._completion_queue.poll() + with self._condition: + self._events.append(event) + self._due.remove(event.tag) + self._condition.notify_all() + if not self._due: + self._returned = True + return + thread = threading.Thread(target=in_thread) + thread.start() + + def events(self, at_least): + with self._condition: + while len(self._events) < at_least: + self._condition.wait() + return tuple(self._events) + + +class CancelManyCallsTest(unittest.TestCase): + + def testCancelManyCalls(self): + server_thread_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + + server_completion_queue = cygrpc.CompletionQueue() + server = cygrpc.Server() + server.register_completion_queue(server_completion_queue) + port = server.add_http2_port('[::]:0') + server.start() + channel = cygrpc.Channel('localhost:{}'.format(port)) + + state = _State() + + server_thread_args = ( + state, server, server_completion_queue, server_thread_pool,) + server_thread = threading.Thread(target=_serve, args=server_thread_args) + server_thread.start() + + client_condition = threading.Condition() + client_due = set() + client_completion_queue = cygrpc.CompletionQueue() + client_driver = _QueueDriver( + client_condition, client_completion_queue, client_due) + client_driver.start() + + with client_condition: + client_calls = [] + for index in range(test_constants.RPC_CONCURRENCY): + client_call = channel.create_call( + None, _EMPTY_FLAGS, client_completion_queue, b'/twinkies', None, + _INFINITE_FUTURE) + operations = ( + cygrpc.operation_send_initial_metadata( + _EMPTY_METADATA, _EMPTY_FLAGS), + cygrpc.operation_send_message(b'\x45\x56', _EMPTY_FLAGS), + cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), + cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), + cygrpc.operation_receive_message(_EMPTY_FLAGS), + cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), + ) + tag = 'client_complete_call_{0:04d}_tag'.format(index) + client_call.start_batch(cygrpc.Operations(operations), tag) + client_due.add(tag) + client_calls.append(client_call) + + with state.condition: + while True: + if state.parked_handlers < test_constants.THREAD_CONCURRENCY: + state.condition.wait() + elif state.handled_rpcs < test_constants.RPC_CONCURRENCY: + state.condition.wait() + else: + state.handlers_released = True + state.condition.notify_all() + break + + client_driver.events( + test_constants.RPC_CONCURRENCY * _SUCCESS_CALL_FRACTION) + with client_condition: + for client_call in client_calls: + client_call.cancel() + + with state.condition: + server.shutdown(server_completion_queue, _SERVER_SHUTDOWN_TAG) + + +if __name__ == '__main__': + unittest.main(verbosity=2) -- cgit v1.2.3 From 15d7f3cd0deb1251ca984b78691fa65ca6cfd969 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 25 May 2016 06:56:45 -0700 Subject: Mark port as non-listening --- src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi | 2 ++ src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src/python/grpcio') diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index 66e6e6b549..d42c58050f 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -336,6 +336,8 @@ cdef extern from "grpc/_cython/loader.h": void grpc_server_register_completion_queue(grpc_server *server, grpc_completion_queue *cq, void *reserved) nogil + void grpc_server_register_non_listening_completion_queue( + grpc_server *server, grpc_completion_queue *cq, void *reserved) nogil int grpc_server_add_insecure_http2_port( grpc_server *server, const char *addr) nogil void grpc_server_start(grpc_server *server) nogil diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi index 8419a59068..55948755b2 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi @@ -81,11 +81,20 @@ cdef class Server: self.c_server, queue.c_completion_queue, NULL) self.registered_completion_queues.append(queue) + def register_non_listening_completion_queue( + self, CompletionQueue queue not None): + if self.is_started: + raise ValueError("cannot register completion queues after start") + with nogil: + grpc_server_register_non_listening_completion_queue( + self.c_server, queue.c_completion_queue, NULL) + self.registered_completion_queues.append(queue) + def start(self): if self.is_started: raise ValueError("the server has already started") self.backup_shutdown_queue = CompletionQueue() - self.register_completion_queue(self.backup_shutdown_queue) + self.register_non_listening_completion_queue(self.backup_shutdown_queue) self.is_started = True with nogil: grpc_server_start(self.c_server) @@ -169,4 +178,3 @@ cdef class Server: time.sleep(0) with nogil: grpc_server_destroy(self.c_server) - -- cgit v1.2.3