Merge pull request #4188 from ctiller/no-transport-metadata
Remove metadata contexts
diff --git a/doc/grpc-auth-support.md b/doc/grpc-auth-support.md
deleted file mode 100644
index b210ff1..0000000
--- a/doc/grpc-auth-support.md
+++ /dev/null
@@ -1,289 +0,0 @@
-#gRPC Authentication support
-
-gRPC is designed to plug-in a number of authentication mechanisms. This document
-provides a quick overview of the various auth mechanisms supported, discusses
-the API with some examples, and concludes with a discussion of extensibility.
-More documentation and examples are coming soon!
-
-## Supported auth mechanisms
-
-###SSL/TLS
-gRPC has SSL/TLS integration and promotes the use of SSL/TLS to authenticate the
-server, and encrypt all the data exchanged between the client and the server.
-Optional mechanisms are available for clients to provide certificates to
-accomplish mutual authentication.
-
-###OAuth 2.0
-gRPC provides a generic mechanism (described below) to attach metadata to
-requests and responses. This mechanism can be used to attach OAuth 2.0 Access
-Tokens to RPCs being made at a client. Additional support for acquiring Access
-Tokens while accessing Google APIs through gRPC is provided for certain auth
-flows, demonstrated through code examples below.
-
-## API
-To reduce complexity and minimize API clutter, gRPC works with a unified concept
-of a Credentials object. Users construct gRPC credentials using corresponding
-bootstrap credentials (e.g., SSL client certs or Service Account Keys), and use
-the credentials while creating a gRPC channel to any server. Depending on the
-type of credential supplied, the channel uses the credentials during the initial
-SSL/TLS handshake with the server, or uses the credential to generate and
-attach Access Tokens to each request being made on the channel.
-
-###SSL/TLS for server authentication and encryption
-This is the simplest authentication scenario, where a client just wants to
-authenticate the server and encrypt all data.
-
-```cpp
-SslCredentialsOptions ssl_opts; // Options to override SSL params, empty by default
-// Create the credentials object by providing service account key in constructor
-std::shared_ptr<ChannelCredentials> creds = SslCredentials(ssl_opts);
-// Create a channel using the credentials created in the previous step
-std::shared_ptr<Channel> channel = CreateChannel(server_name, creds);
-// Create a stub on the channel
-std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
-// Make actual RPC calls on the stub.
-grpc::Status s = stub->sayHello(&context, *request, response);
-```
-
-For advanced use cases such as modifying the root CA or using client certs,
-the corresponding options can be set in the SslCredentialsOptions parameter
-passed to the factory method.
-
-
-###Authenticating with Google
-
-gRPC applications can use a simple API to create a credential that works in various deployment scenarios.
-
-```cpp
-std::shared_ptr<ChannelCredentials> creds = GoogleDefaultCredentials();
-// Create a channel, stub and make RPC calls (same as in the previous example)
-std::shared_ptr<Channel> channel = CreateChannel(server_name, creds);
-std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
-grpc::Status s = stub->sayHello(&context, *request, response);
-```
-
-This credential works for applications using Service Accounts as well as for
-applications running in [Google Compute Engine (GCE)](https://cloud.google.com/compute/). In the former case, the
-service account’s private keys are loaded from the file named in the environment
-variable `GOOGLE_APPLICATION_CREDENTIALS`. The
-keys are used to generate bearer tokens that are attached to each outgoing RPC
-on the corresponding channel.
-
-For applications running in GCE, a default service account and corresponding
-OAuth scopes can be configured during VM setup. At run-time, this credential
-handles communication with the authentication systems to obtain OAuth2 access
-tokens and attaches them to each outgoing RPC on the corresponding channel.
-Extending gRPC to support other authentication mechanisms
-The gRPC protocol is designed with a general mechanism for sending metadata
-associated with RPC. Clients can send metadata at the beginning of an RPC and
-servers can send back metadata at the beginning and end of the RPC. This
-provides a natural mechanism to support OAuth2 and other authentication
-mechanisms that need attach bearer tokens to individual request.
-
-In the simplest case, there is a single line of code required on the client
-to add a specific token as metadata to an RPC and a corresponding access on
-the server to retrieve this piece of metadata. The generation of the token
-on the client side and its verification at the server can be done separately.
-
-A deeper integration can be achieved by plugging in a gRPC credentials implementation for any custom authentication mechanism that needs to attach per-request tokens. gRPC internals also allow switching out SSL/TLS with other encryption mechanisms.
-
-## Examples
-
-These authentication mechanisms will be available in all gRPC's supported languages.
-The following sections demonstrate how authentication and authorization features described above appear in each language: more languages are coming soon.
-
-###SSL/TLS for server authentication and encryption (Ruby)
-```ruby
-# Base case - No encryption
-stub = Helloworld::Greeter::Stub.new('localhost:50051')
-...
-
-# With server authentication SSL/TLS
-creds = GRPC::Core::Credentials.new(load_certs) # load_certs typically loads a CA roots file
-stub = Helloworld::Greeter::Stub.new('localhost:50051', creds: creds)
-```
-
-###SSL/TLS for server authentication and encryption (C#)
-```csharp
-// Base case - No encryption
-var channel = new Channel("localhost:50051");
-var client = new Greeter.GreeterClient(channel);
-...
-
-// With server authentication SSL/TLS
-var credentials = new SslCredentials(File.ReadAllText("ca.pem")); // Load a CA file
-var channel = new Channel("localhost:50051", credentials);
-var client = new Greeter.GreeterClient(channel);
-```
-
-###SSL/TLS for server authentication and encryption (Objective-C)
-
-The default for Objective-C is to use SSL/TLS, as that's the most common use case when accessing
-remote APIs.
-
-```objective-c
-// Base case - With server authentication SSL/TLS
-HLWGreeter *client = [[HLWGreeter alloc] initWithHost:@"localhost:50051"];
-// Same as using @"https://localhost:50051".
-...
-
-// No encryption
-HLWGreeter *client = [[HLWGreeter alloc] initWithHost:@"http://localhost:50051"];
-// Specifying the HTTP scheme explicitly forces no encryption.
-```
-
-###SSL/TLS for server authentication and encryption (Python)
-```python
-# Base case - No encryption
-stub = early_adopter_create_GreeterService_stub('localhost', 50051)
-...
-
-# With server authentication SSL/TLS
-stub = early_adopter_create_GreeterService_stub(
- 'localhost', 50051, secure=True, root_certificates=open('ca.pem').read())
-...
-```
-n.b.: the beta API will look different
-
-###Authenticating with Google (Ruby)
-```ruby
-# Base case - No encryption/authorization
-stub = Helloworld::Greeter::Stub.new('localhost:50051')
-...
-
-# Authenticating with Google
-require 'googleauth' # from http://www.rubydoc.info/gems/googleauth/0.1.0
-...
-creds = GRPC::Core::Credentials.new(load_certs) # load_certs typically loads a CA roots file
-scope = 'https://www.googleapis.com/auth/grpc-testing'
-authorization = Google::Auth.get_application_default(scope)
-stub = Helloworld::Greeter::Stub.new('localhost:50051',
- creds: creds,
- update_metadata: authorization.updater_proc)
-```
-
-###Authenticating with Google (Node.js)
-
-```node
-// Base case - No encryption/authorization
-var stub = new helloworld.Greeter('localhost:50051');
-...
-// Authenticating with Google
-var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library
-...
-var creds = grpc.Credentials.createSsl(load_certs); // load_certs typically loads a CA roots file
-var scope = 'https://www.googleapis.com/auth/grpc-testing';
-(new GoogleAuth()).getApplicationDefault(function(err, auth) {
- if (auth.createScopeRequired()) {
- auth = auth.createScoped(scope);
- }
- var stub = new helloworld.Greeter('localhost:50051',
- {credentials: creds},
- grpc.getGoogleAuthDelegate(auth));
-});
-```
-
-###Authenticating with Google (C#)
-```csharp
-// Base case - No encryption/authorization
-var channel = new Channel("localhost:50051");
-var client = new Greeter.GreeterClient(channel);
-...
-
-// Authenticating with Google
-using Grpc.Auth; // from Grpc.Auth NuGet package
-...
-var credentials = new SslCredentials(File.ReadAllText("ca.pem")); // Load a CA file
-var channel = new Channel("localhost:50051", credentials);
-
-string scope = "https://www.googleapis.com/auth/grpc-testing";
-var authorization = GoogleCredential.GetApplicationDefault();
-if (authorization.IsCreateScopedRequired)
-{
- authorization = credential.CreateScoped(new[] { scope });
-}
-var client = new Greeter.GreeterClient(channel,
- new StubConfiguration(OAuth2InterceptorFactory.Create(credential)));
-```
-
-###Authenticating with Google (PHP)
-```php
-// Base case - No encryption/authorization
-$client = new helloworld\GreeterClient(
- new Grpc\BaseStub('localhost:50051', []));
-...
-
-// Authenticating with Google
-// the environment variable "GOOGLE_APPLICATION_CREDENTIALS" needs to be set
-$scope = "https://www.googleapis.com/auth/grpc-testing";
-$auth = Google\Auth\ApplicationDefaultCredentials::getCredentials($scope);
-$opts = [
- 'credentials' => Grpc\Credentials::createSsl(file_get_contents('ca.pem'));
- 'update_metadata' => $auth->getUpdateMetadataFunc(),
-];
-
-$client = new helloworld\GreeterClient(
- new Grpc\BaseStub('localhost:50051', $opts));
-
-```
-
-###Authenticating with Google (Objective-C)
-
-This example uses the [Google iOS Sign-In library](https://developers.google.com/identity/sign-in/ios/),
-but it's easily extrapolated to any other OAuth2 library.
-
-```objective-c
-// Base case - No authentication
-[client sayHelloWithRequest:request handler:^(HLWHelloReply *response, NSError *error) {
- ...
-}];
-
-...
-
-// Authenticating with Google
-
-// When signing the user in, ask her for the relevant scopes.
-GIDSignIn.sharedInstance.scopes = @[@"https://www.googleapis.com/auth/grpc-testing"];
-
-...
-
-#import <ProtoRPC/ProtoRPC.h>
-
-// Create a not-yet-started RPC. We want to set the request headers on this object before starting
-// it.
-ProtoRPC *call =
- [client RPCToSayHelloWithRequest:request handler:^(HLWHelloReply *response, NSError *error) {
- ...
- }];
-
-// Set the access token to be used.
-NSString *accessToken = GIDSignIn.sharedInstance.currentUser.authentication.accessToken;
-call.requestMetadata[@"Authorization"] = [@"Bearer " stringByAppendingString:accessToken]}];
-
-// Start the RPC.
-[call start];
-```
-
-You can see a working example app, with a more detailed explanation, [here](examples/objective-c/auth_sample).
-
-### Authenticating with Google (Python)
-```python
-# Base case - No encryption
-stub = early_adopter_create_GreeterService_stub('localhost', 50051)
-...
-
-# With server authentication SSL/TLS
-import oauth2client.client
-credentials = oauth2client.GoogleCredentials.get_application_default()
-scope = 'https://www.googleapis.com/auth/grpc-testing'
-scoped_credentials = credentials.create_scoped([scope])
-access_token = scoped_credentials.get_access_token().access_token
-metadata_transformer = (
- lambda x: [('Authorization', 'Bearer {}'.format(access_token))])
-
-stub = early_adopter_create_GreeterService_stub(
- 'localhost', 50051, secure=True, root_certificates=open('ca.pem').read(),
- metadata_transformer=metadata_transformer)
-...
-```
-n.b.: the beta API will look different
diff --git a/examples/objective-c/auth_sample/AuthTestService.podspec b/examples/objective-c/auth_sample/AuthTestService.podspec
index 9521d49..e935626 100644
--- a/examples/objective-c/auth_sample/AuthTestService.podspec
+++ b/examples/objective-c/auth_sample/AuthTestService.podspec
@@ -29,7 +29,7 @@
ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
ss.header_mappings_dir = dir
ss.requires_arc = true
- ss.dependency "gRPC", "~> 0.11"
+ ss.dependency "gRPC", "~> 0.12"
ss.dependency "#{s.name}/Messages"
end
end
diff --git a/examples/objective-c/helloworld/HelloWorld.podspec b/examples/objective-c/helloworld/HelloWorld.podspec
index 600898f..bdf782f 100644
--- a/examples/objective-c/helloworld/HelloWorld.podspec
+++ b/examples/objective-c/helloworld/HelloWorld.podspec
@@ -29,7 +29,7 @@
ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
ss.header_mappings_dir = dir
ss.requires_arc = true
- ss.dependency "gRPC", "~> 0.11"
+ ss.dependency "gRPC", "~> 0.12"
ss.dependency "#{s.name}/Messages"
end
end
diff --git a/examples/objective-c/route_guide/RouteGuide.podspec b/examples/objective-c/route_guide/RouteGuide.podspec
index e00f827..4bc2c42 100644
--- a/examples/objective-c/route_guide/RouteGuide.podspec
+++ b/examples/objective-c/route_guide/RouteGuide.podspec
@@ -29,7 +29,7 @@
ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
ss.header_mappings_dir = dir
ss.requires_arc = true
- ss.dependency "gRPC", "~> 0.11"
+ ss.dependency "gRPC", "~> 0.12"
ss.dependency "#{s.name}/Messages"
end
end
diff --git a/gRPC.podspec b/gRPC.podspec
index 777638e..0262479 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -36,7 +36,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
- version = '0.11.2'
+ version = '0.12.0'
s.version = version
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'http://www.grpc.io'
@@ -589,7 +589,7 @@
ss.requires_arc = false
ss.libraries = 'z'
- ss.dependency 'OpenSSL', '~> 1.0.200'
+ ss.dependency 'OpenSSL', '~> 1.0.204.1'
# ss.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w'
end
diff --git a/include/grpc++/security/credentials.h b/include/grpc++/security/credentials.h
index cc827f0..e5652dc 100644
--- a/include/grpc++/security/credentials.h
+++ b/include/grpc++/security/credentials.h
@@ -38,6 +38,7 @@
#include <memory>
#include <grpc++/impl/grpc_library.h>
+#include <grpc++/security/auth_context.h>
#include <grpc++/support/config.h>
#include <grpc++/support/status.h>
#include <grpc++/support/string_ref.h>
@@ -206,9 +207,17 @@
// a different thread from the one processing the call.
virtual bool IsBlocking() const { return true; }
+ // Type of credentials this plugin is implementing.
+ virtual const char* GetType() const { return ""; }
+
// Gets the auth metatada produced by this plugin.
+ // The fully qualified method name is:
+ // service_url + "/" + method_name.
+ // The channel_auth_context contains (among other things), the identity of
+ // the server.
virtual Status GetMetadata(
- grpc::string_ref service_url,
+ grpc::string_ref service_url, grpc::string_ref method_name,
+ const AuthContext& channel_auth_context,
std::multimap<grpc::string, grpc::string>* metadata) = 0;
};
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index c8da593..655f45a 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -41,6 +41,81 @@
extern "C" {
#endif
+/* --- Authentication Context. --- */
+
+#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
+#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
+
+#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
+#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
+
+typedef struct grpc_auth_context grpc_auth_context;
+
+typedef struct grpc_auth_property_iterator {
+ const grpc_auth_context *ctx;
+ size_t index;
+ const char *name;
+} grpc_auth_property_iterator;
+
+/* value, if not NULL, is guaranteed to be NULL terminated. */
+typedef struct grpc_auth_property {
+ char *name;
+ char *value;
+ size_t value_length;
+} grpc_auth_property;
+
+/* Returns NULL when the iterator is at the end. */
+const grpc_auth_property *grpc_auth_property_iterator_next(
+ grpc_auth_property_iterator *it);
+
+/* Iterates over the auth context. */
+grpc_auth_property_iterator grpc_auth_context_property_iterator(
+ const grpc_auth_context *ctx);
+
+/* Gets the peer identity. Returns an empty iterator (first _next will return
+ NULL) if the peer is not authenticated. */
+grpc_auth_property_iterator grpc_auth_context_peer_identity(
+ const grpc_auth_context *ctx);
+
+/* Finds a property in the context. May return an empty iterator (first _next
+ will return NULL) if no property with this name was found in the context. */
+grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
+ const grpc_auth_context *ctx, const char *name);
+
+/* Gets the name of the property that indicates the peer identity. Will return
+ NULL if the peer is not authenticated. */
+const char *grpc_auth_context_peer_identity_property_name(
+ const grpc_auth_context *ctx);
+
+/* Returns 1 if the peer is authenticated, 0 otherwise. */
+int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
+
+/* Gets the auth context from the call. Caller needs to call
+ grpc_auth_context_release on the returned context. */
+grpc_auth_context *grpc_call_auth_context(grpc_call *call);
+
+/* Releases the auth context returned from grpc_call_auth_context. */
+void grpc_auth_context_release(grpc_auth_context *context);
+
+/* --
+ The following auth context methods should only be called by a server metadata
+ processor to set properties extracted from auth metadata.
+ -- */
+
+/* Add a property. */
+void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
+ const char *value, size_t value_length);
+
+/* Add a C string property. */
+void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
+ const char *name,
+ const char *value);
+
+/* Sets the property name. Returns 1 if successful or 0 in case of failure
+ (which means that no property with this name exists). */
+int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
+ const char *name);
+
/* --- grpc_channel_credentials object. ---
A channel credentials object represents a way to authenticate a client on a
@@ -165,6 +240,24 @@
void *user_data, const grpc_metadata *creds_md, size_t num_creds_md,
grpc_status_code status, const char *error_details);
+/* Context that can be used by metadata credentials plugin in order to create
+ auth related metadata. */
+typedef struct {
+ /* The fully qualifed service url. */
+ const char *service_url;
+
+ /* The method name of the RPC being called (not fully qualified).
+ The fully qualified method name can be built from the service_url:
+ full_qualified_method_name = ctx->service_url + '/' + ctx->method_name. */
+ const char *method_name;
+
+ /* The auth_context of the channel which gives the server's identity. */
+ const grpc_auth_context *channel_auth_context;
+
+ /* Reserved for future use. */
+ void *reserved;
+} grpc_auth_metadata_context;
+
/* grpc_metadata_credentials plugin is an API user provided structure used to
create grpc_credentials objects that can be set on a channel (composed) or
a call. See grpc_credentials_metadata_create_from_plugin below.
@@ -172,11 +265,11 @@
every call in scope for the credentials created from it. */
typedef struct {
/* The implementation of this method has to be non-blocking.
- - service_url is the fully qualified URL that the client stack is
- connecting to.
+ - context is the information that can be used by the plugin to create auth
+ metadata.
- cb is the callback that needs to be called when the metadata is ready.
- user_data needs to be passed as the first parameter of the callback. */
- void (*get_metadata)(void *state, const char *service_url,
+ void (*get_metadata)(void *state, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb, void *user_data);
/* Destroys the plugin state. */
@@ -184,6 +277,9 @@
/* State that will be set as the first parameter of the methods above. */
void *state;
+
+ /* Type of credentials that this plugin is implementing. */
+ const char *type;
} grpc_metadata_credentials_plugin;
/* Creates a credentials object from a plugin. */
@@ -239,81 +335,6 @@
grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_call_credentials *creds);
-/* --- Authentication Context. --- */
-
-#define GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME "transport_security_type"
-#define GRPC_SSL_TRANSPORT_SECURITY_TYPE "ssl"
-
-#define GRPC_X509_CN_PROPERTY_NAME "x509_common_name"
-#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
-
-typedef struct grpc_auth_context grpc_auth_context;
-
-typedef struct grpc_auth_property_iterator {
- const grpc_auth_context *ctx;
- size_t index;
- const char *name;
-} grpc_auth_property_iterator;
-
-/* value, if not NULL, is guaranteed to be NULL terminated. */
-typedef struct grpc_auth_property {
- char *name;
- char *value;
- size_t value_length;
-} grpc_auth_property;
-
-/* Returns NULL when the iterator is at the end. */
-const grpc_auth_property *grpc_auth_property_iterator_next(
- grpc_auth_property_iterator *it);
-
-/* Iterates over the auth context. */
-grpc_auth_property_iterator grpc_auth_context_property_iterator(
- const grpc_auth_context *ctx);
-
-/* Gets the peer identity. Returns an empty iterator (first _next will return
- NULL) if the peer is not authenticated. */
-grpc_auth_property_iterator grpc_auth_context_peer_identity(
- const grpc_auth_context *ctx);
-
-/* Finds a property in the context. May return an empty iterator (first _next
- will return NULL) if no property with this name was found in the context. */
-grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
- const grpc_auth_context *ctx, const char *name);
-
-/* Gets the name of the property that indicates the peer identity. Will return
- NULL if the peer is not authenticated. */
-const char *grpc_auth_context_peer_identity_property_name(
- const grpc_auth_context *ctx);
-
-/* Returns 1 if the peer is authenticated, 0 otherwise. */
-int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
-
-/* Gets the auth context from the call. Caller needs to call
- grpc_auth_context_release on the returned context. */
-grpc_auth_context *grpc_call_auth_context(grpc_call *call);
-
-/* Releases the auth context returned from grpc_call_auth_context. */
-void grpc_auth_context_release(grpc_auth_context *context);
-
-/* --
- The following auth context methods should only be called by a server metadata
- processor to set properties extracted from auth metadata.
- -- */
-
-/* Add a property. */
-void grpc_auth_context_add_property(grpc_auth_context *ctx, const char *name,
- const char *value, size_t value_length);
-
-/* Add a C string property. */
-void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
- const char *name,
- const char *value);
-
-/* Sets the property name. Returns 1 if successful or 0 in case of failure
- (which means that no property with this name exists). */
-int grpc_auth_context_set_peer_identity_property_name(grpc_auth_context *ctx,
- const char *name);
-
/* --- Auth Metadata Processing --- */
/* Callback function that is called when the metadata processing is done.
diff --git a/package.json b/package.json
index 1fd0ffb..9517c59 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "grpc",
- "version": "0.11.1",
+ "version": "0.12.0",
"author": "Google Inc.",
"description": "gRPC Library for Node",
"homepage": "http://www.grpc.io/",
diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c
index 7ff80e6..2be0ea2 100644
--- a/src/core/iomgr/fd_posix.c
+++ b/src/core/iomgr/fd_posix.c
@@ -207,14 +207,21 @@
}
void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
- const char *reason) {
+ int *release_fd, const char *reason) {
fd->on_done_closure = on_done;
- shutdown(fd->fd, SHUT_RDWR);
+ 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)) {
fd->closed = 1;
- close(fd->fd);
+ if (!fd->released) {
+ close(fd->fd);
+ }
grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, 1);
} else {
wake_all_watchers_locked(fd);
@@ -406,7 +413,9 @@
}
if (grpc_fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) {
fd->closed = 1;
- close(fd->fd);
+ if (!fd->released) {
+ close(fd->fd);
+ }
grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, 1);
}
gpr_mu_unlock(&fd->mu);
diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h
index dc917eb..d628ef3 100644
--- a/src/core/iomgr/fd_posix.h
+++ b/src/core/iomgr/fd_posix.h
@@ -62,6 +62,7 @@
gpr_mu mu;
int shutdown;
int closed;
+ int released;
/* The watcher list.
@@ -107,11 +108,12 @@
/* Releases fd to be asynchronously destroyed.
on_done is called when the underlying file descriptor is definitely close()d.
If on_done is NULL, no callback will be made.
+ If release_fd is not NULL, it's set to fd and fd will not be closed.
Requires: *fd initialized; no outstanding notify_on_read or
notify_on_write.
MUST NOT be called with a pollset lock taken */
void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
- const char *reason);
+ int *release_fd, const char *reason);
/* Begin polling on an fd.
Registers that the given pollset is interested in this fd - so that if read
diff --git a/src/core/iomgr/tcp_client_posix.c b/src/core/iomgr/tcp_client_posix.c
index abd6315..d9d24ee 100644
--- a/src/core/iomgr/tcp_client_posix.c
+++ b/src/core/iomgr/tcp_client_posix.c
@@ -196,7 +196,7 @@
finish:
if (fd != NULL) {
grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
- grpc_fd_orphan(exec_ctx, fd, NULL, "tcp_client_orphan");
+ grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan");
fd = NULL;
}
done = (--ac->refs == 0);
@@ -265,7 +265,7 @@
if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
- grpc_fd_orphan(exec_ctx, fdobj, NULL, "tcp_client_connect_error");
+ grpc_fd_orphan(exec_ctx, fdobj, NULL, NULL, "tcp_client_connect_error");
grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
goto done;
}
diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c
index 915553d..f3be41a 100644
--- a/src/core/iomgr/tcp_posix.c
+++ b/src/core/iomgr/tcp_posix.c
@@ -90,6 +90,8 @@
grpc_closure *read_cb;
grpc_closure *write_cb;
+ grpc_closure *release_fd_cb;
+ int *release_fd;
grpc_closure read_closure;
grpc_closure write_closure;
@@ -108,7 +110,8 @@
}
static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
- grpc_fd_orphan(exec_ctx, tcp->em_fd, NULL, "tcp_unref_orphan");
+ grpc_fd_orphan(exec_ctx, tcp->em_fd, tcp->release_fd_cb, tcp->release_fd,
+ "tcp_unref_orphan");
gpr_slice_buffer_destroy(&tcp->last_read_buffer);
gpr_free(tcp->peer_string);
gpr_free(tcp);
@@ -452,6 +455,8 @@
tcp->fd = em_fd->fd;
tcp->read_cb = NULL;
tcp->write_cb = NULL;
+ tcp->release_fd_cb = NULL;
+ tcp->release_fd = NULL;
tcp->incoming_buffer = NULL;
tcp->slice_size = slice_size;
tcp->iov_size = 1;
@@ -468,4 +473,13 @@
return &tcp->base;
}
+void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+ int *fd, grpc_closure *done) {
+ grpc_tcp *tcp = (grpc_tcp *)ep;
+ GPR_ASSERT(ep->vtable == &vtable);
+ tcp->release_fd = fd;
+ tcp->release_fd_cb = done;
+ TCP_UNREF(exec_ctx, tcp, "destroy");
+}
+
#endif
diff --git a/src/core/iomgr/tcp_posix.h b/src/core/iomgr/tcp_posix.h
index 40b3ae2..b554983 100644
--- a/src/core/iomgr/tcp_posix.h
+++ b/src/core/iomgr/tcp_posix.h
@@ -56,4 +56,10 @@
grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size,
const char *peer_string);
+/* Destroy the tcp endpoint without closing its fd. *fd will be set and done
+ * will be called when the endpoint is destroyed.
+ * Requires: ep must be a tcp endpoint and fd must not be NULL. */
+void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
+ int *fd, grpc_closure *done);
+
#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_POSIX_H */
diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c
index 0ece77c..a89ee02 100644
--- a/src/core/iomgr/tcp_server_posix.c
+++ b/src/core/iomgr/tcp_server_posix.c
@@ -193,7 +193,7 @@
}
sp->destroyed_closure.cb = destroyed_port;
sp->destroyed_closure.cb_arg = s;
- grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure,
+ grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
"tcp_listener_shutdown");
}
gpr_mu_unlock(&s->mu);
diff --git a/src/core/iomgr/udp_server.c b/src/core/iomgr/udp_server.c
index 9903e97..782fbd9 100644
--- a/src/core/iomgr/udp_server.c
+++ b/src/core/iomgr/udp_server.c
@@ -179,7 +179,7 @@
}
sp->destroyed_closure.cb = destroyed_port;
sp->destroyed_closure.cb_arg = s;
- grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure,
+ grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
"udp_listener_shutdown");
}
gpr_mu_unlock(&s->mu);
diff --git a/src/core/iomgr/workqueue_posix.c b/src/core/iomgr/workqueue_posix.c
index c087b88..2e30178 100644
--- a/src/core/iomgr/workqueue_posix.c
+++ b/src/core/iomgr/workqueue_posix.c
@@ -115,7 +115,7 @@
/* HACK: let wakeup_fd code know that we stole the fd */
workqueue->wakeup_fd.read_fd = 0;
grpc_wakeup_fd_destroy(&workqueue->wakeup_fd);
- grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, "destroy");
+ grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy");
gpr_free(workqueue);
} else {
gpr_mu_lock(&workqueue->mu);
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
index cd4b39f..4e5be03 100644
--- a/src/core/security/client_auth_filter.c
+++ b/src/core/security/client_auth_filter.c
@@ -62,7 +62,7 @@
grpc_transport_stream_op op;
gpr_uint8 security_context_set;
grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
- char *service_url;
+ grpc_auth_metadata_context auth_md_context;
} call_data;
/* We can have a per-channel credentials. */
@@ -70,11 +70,20 @@
grpc_channel_security_connector *security_connector;
} channel_data;
-static void reset_service_url(call_data *calld) {
- if (calld->service_url != NULL) {
- gpr_free(calld->service_url);
- calld->service_url = NULL;
+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,
@@ -94,7 +103,7 @@
grpc_transport_stream_op *op = &calld->op;
grpc_metadata_batch *mdb;
size_t i;
- reset_service_url(calld);
+ 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.");
@@ -112,9 +121,13 @@
grpc_call_next_op(exec_ctx, elem, op);
}
-void build_service_url(const char *url_scheme, call_data *calld) {
+void build_auth_metadata_context(grpc_security_connector *sc,
+ 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';
@@ -123,11 +136,16 @@
service[1] = '\0';
} else {
*last_slash = '\0';
+ method_name = gpr_strdup(last_slash + 1);
}
- if (url_scheme == NULL) url_scheme = "";
- reset_service_url(calld);
- gpr_asprintf(&calld->service_url, "%s://%s%s", url_scheme,
+ 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(sc->auth_context, "grpc_auth_metadata_context");
gpr_free(service);
}
@@ -161,12 +179,12 @@
call_creds_has_md ? ctx->creds : channel_call_creds);
}
- build_service_url(chand->security_connector->base.url_scheme, calld);
+ build_auth_metadata_context(&chand->security_connector->base, 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->service_url,
- on_credentials_metadata, elem);
+ 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,
@@ -280,7 +298,7 @@
if (calld->method != NULL) {
GRPC_MDSTR_UNREF(calld->method);
}
- reset_service_url(calld);
+ reset_auth_metadata_context(&calld->auth_md_context);
}
/* Constructor for channel_data */
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index f7a2e73..543c750 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -33,16 +33,16 @@
#include "src/core/security/credentials.h"
-#include <string.h>
#include <stdio.h>
+#include <string.h>
#include "src/core/channel/channel_args.h"
#include "src/core/channel/http_client_filter.h"
-#include "src/core/json/json.h"
#include "src/core/httpcli/httpcli.h"
#include "src/core/iomgr/iomgr.h"
-#include "src/core/surface/api_trace.h"
+#include "src/core/json/json.h"
#include "src/core/support/string.h"
+#include "src/core/surface/api_trace.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@@ -116,19 +116,17 @@
grpc_call_credentials_unref(creds);
}
-void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
- grpc_call_credentials *creds,
- grpc_pollset *pollset,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+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, service_url, cb,
+ creds->vtable->get_request_metadata(exec_ctx, creds, pollset, context, cb,
user_data);
}
@@ -429,7 +427,7 @@
static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
- const char *service_url,
+ grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_service_account_jwt_access_credentials *c =
@@ -442,7 +440,7 @@
{
gpr_mu_lock(&c->cache_mu);
if (c->cached.service_url != NULL &&
- strcmp(c->cached.service_url, service_url) == 0 &&
+ 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)),
@@ -457,14 +455,15 @@
/* Generate a new jwt. */
gpr_mu_lock(&c->cache_mu);
jwt_reset_cache(c);
- jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
+ 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(service_url);
+ 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);
@@ -649,7 +648,7 @@
static void oauth2_token_fetcher_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
- grpc_pollset *pollset, const char *service_url,
+ 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;
@@ -804,12 +803,10 @@
grpc_exec_ctx_finish(&exec_ctx);
}
-static void md_only_test_get_request_metadata(grpc_exec_ctx *exec_ctx,
- grpc_call_credentials *creds,
- grpc_pollset *pollset,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+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) {
@@ -846,12 +843,10 @@
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,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+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);
}
@@ -932,7 +927,7 @@
grpc_composite_call_credentials *composite_creds;
size_t creds_index;
grpc_credentials_md_store *md_elems;
- char *service_url;
+ grpc_auth_metadata_context auth_md_context;
void *user_data;
grpc_pollset *pollset;
grpc_credentials_metadata_cb cb;
@@ -950,7 +945,6 @@
static void composite_call_md_context_destroy(
grpc_composite_call_credentials_metadata_context *ctx) {
grpc_credentials_md_store_unref(ctx->md_elems);
- if (ctx->service_url != NULL) gpr_free(ctx->service_url);
gpr_free(ctx);
}
@@ -978,9 +972,9 @@
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->service_url,
- composite_call_metadata_cb, ctx);
+ grpc_call_credentials_get_request_metadata(
+ exec_ctx, inner_creds, ctx->pollset, ctx->auth_md_context,
+ composite_call_metadata_cb, ctx);
return;
}
@@ -990,26 +984,24 @@
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,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data) {
+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->service_url = gpr_strdup(service_url);
+ 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, service_url,
- composite_call_metadata_cb, ctx);
+ 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 = {
@@ -1103,7 +1095,7 @@
static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
- const char *service_url,
+ grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
@@ -1192,7 +1184,7 @@
static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
- const char *service_url,
+ grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
@@ -1201,7 +1193,7 @@
memset(request, 0, sizeof(*request));
request->user_data = user_data;
request->cb = cb;
- c->plugin.get_metadata(c->plugin.state, service_url,
+ 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);
@@ -1218,7 +1210,7 @@
(reserved));
GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(*c));
- c->base.type = GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN;
+ c->base.type = plugin.type;
c->base.vtable = &plugin_vtable;
gpr_ref_init(&c->base.refcount, 1);
c->plugin = plugin;
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 1320609..6d45895 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -59,7 +59,6 @@
"FakeTransportSecurity"
#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
-#define GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
#define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam"
#define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite"
@@ -162,7 +161,7 @@
void (*destruct)(grpc_call_credentials *c);
void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *c, grpc_pollset *pollset,
- const char *service_url,
+ grpc_auth_metadata_context context,
grpc_credentials_metadata_cb cb,
void *user_data);
} grpc_call_credentials_vtable;
@@ -175,12 +174,10 @@
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,
- const char *service_url,
- grpc_credentials_metadata_cb cb,
- void *user_data);
+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;
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index a1b9a30..6409323 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -37,6 +37,7 @@
#include <grpc++/support/channel_arguments.h>
#include "src/cpp/client/create_channel_internal.h"
#include "src/cpp/client/secure_credentials.h"
+#include "src/cpp/common/secure_auth_context.h"
namespace grpc {
@@ -160,7 +161,7 @@
}
void MetadataCredentialsPluginWrapper::GetMetadata(
- void* wrapper, const char* service_url,
+ void* wrapper, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb, void* user_data) {
GPR_ASSERT(wrapper);
MetadataCredentialsPluginWrapper* w =
@@ -171,18 +172,25 @@
}
if (w->plugin_->IsBlocking()) {
w->thread_pool_->Add(
- std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w,
- service_url, cb, user_data));
+ std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w, context,
+ cb, user_data));
} else {
- w->InvokePlugin(service_url, cb, user_data);
+ w->InvokePlugin(context, cb, user_data);
}
}
void MetadataCredentialsPluginWrapper::InvokePlugin(
- const char* service_url, grpc_credentials_plugin_metadata_cb cb,
+ grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb,
void* user_data) {
std::multimap<grpc::string, grpc::string> metadata;
- Status status = plugin_->GetMetadata(service_url, &metadata);
+
+ // const_cast is safe since the SecureAuthContext does not take owndership and
+ // the object is passed as a const ref to plugin_->GetMetadata.
+ SecureAuthContext cpp_channel_auth_context(
+ const_cast<grpc_auth_context*>(context.channel_auth_context), false);
+
+ Status status = plugin_->GetMetadata(context.service_url, context.method_name,
+ cpp_channel_auth_context, &metadata);
std::vector<grpc_metadata> md;
for (auto it = metadata.begin(); it != metadata.end(); ++it) {
grpc_metadata md_entry;
@@ -204,11 +212,12 @@
std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin> plugin) {
GrpcLibrary init; // To call grpc_init().
+ const char* type = plugin->GetType();
MetadataCredentialsPluginWrapper* wrapper =
new MetadataCredentialsPluginWrapper(std::move(plugin));
grpc_metadata_credentials_plugin c_plugin = {
MetadataCredentialsPluginWrapper::GetMetadata,
- MetadataCredentialsPluginWrapper::Destroy, wrapper};
+ MetadataCredentialsPluginWrapper::Destroy, wrapper, type};
return WrapCallCredentials(
grpc_metadata_credentials_create_from_plugin(c_plugin, nullptr));
}
diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h
index e9afa9e..cef5929 100644
--- a/src/cpp/client/secure_credentials.h
+++ b/src/cpp/client/secure_credentials.h
@@ -79,7 +79,7 @@
class MetadataCredentialsPluginWrapper GRPC_FINAL {
public:
static void Destroy(void* wrapper);
- static void GetMetadata(void* wrapper, const char* service_url,
+ static void GetMetadata(void* wrapper, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void* user_data);
@@ -87,7 +87,7 @@
std::unique_ptr<MetadataCredentialsPlugin> plugin);
private:
- void InvokePlugin(const char* service_url,
+ void InvokePlugin(grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb, void* user_data);
std::unique_ptr<ThreadPoolInterface> thread_pool_;
std::unique_ptr<MetadataCredentialsPlugin> plugin_;
diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs
index e9ec30e..818ddb8 100644
--- a/src/csharp/Grpc.Core/VersionInfo.cs
+++ b/src/csharp/Grpc.Core/VersionInfo.cs
@@ -41,6 +41,6 @@
/// <summary>
/// Current version of gRPC C#
/// </summary>
- public const string CurrentVersion = "0.7.1";
+ public const string CurrentVersion = "0.12.0";
}
}
diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat
index b864a95..45f6b26 100644
--- a/src/csharp/build_packages.bat
+++ b/src/csharp/build_packages.bat
@@ -1,8 +1,8 @@
@rem Builds gRPC NuGet packages
@rem Current package versions
-set VERSION=0.7.1
-set CORE_VERSION=0.11.1
+set VERSION=0.12.0
+set CORE_VERSION=0.12.0
set PROTOBUF_VERSION=3.0.0-alpha4
@rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well.
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 1839319..b8705c4 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -930,11 +930,12 @@
void *state, const char *service_url, grpc_credentials_plugin_metadata_cb cb,
void *user_data, gpr_int32 is_destroy);
-static void grpcsharp_get_metadata_handler(void *state, const char *service_url,
- grpc_credentials_plugin_metadata_cb cb, void *user_data) {
+static void grpcsharp_get_metadata_handler(
+ void *state, grpc_auth_metadata_context context,
+ grpc_credentials_plugin_metadata_cb cb, void *user_data) {
grpcsharp_metadata_interceptor_func interceptor =
(grpcsharp_metadata_interceptor_func)(gpr_intptr)state;
- interceptor(state, service_url, cb, user_data, 0);
+ interceptor(state, context.service_url, cb, user_data, 0);
}
static void grpcsharp_metadata_credentials_destroy_handler(void *state) {
@@ -949,6 +950,7 @@
plugin.get_metadata = grpcsharp_get_metadata_handler;
plugin.destroy = grpcsharp_metadata_credentials_destroy_handler;
plugin.state = (void*)(gpr_intptr)metadata_interceptor;
+ plugin.type = "";
return grpc_metadata_credentials_create_from_plugin(plugin, NULL);
}
diff --git a/src/node/ext/byte_buffer.cc b/src/node/ext/byte_buffer.cc
index e1786dd..c306292 100644
--- a/src/node/ext/byte_buffer.cc
+++ b/src/node/ext/byte_buffer.cc
@@ -77,6 +77,7 @@
while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
memcpy(result + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next));
offset += GPR_SLICE_LENGTH(next);
+ gpr_slice_unref(next);
}
return scope.Escape(MakeFastBuffer(
Nan::NewBuffer(result, length).ToLocalChecked()));
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index a98ae85..c0e2b0f 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -234,6 +234,14 @@
class SendMessageOp : public Op {
public:
+ SendMessageOp() {
+ send_message = NULL;
+ }
+ ~SendMessageOp() {
+ if (send_message != NULL) {
+ grpc_byte_buffer_destroy(send_message);
+ }
+ }
Local<Value> GetNodeValue() const {
EscapableHandleScope scope;
return scope.Escape(Nan::True());
@@ -253,7 +261,8 @@
out->flags = maybe_flag.FromMaybe(0) & GRPC_WRITE_USED_MASK;
}
}
- out->data.send_message = BufferToByteBuffer(value);
+ send_message = BufferToByteBuffer(value);
+ out->data.send_message = send_message;
PersistentValue *handle = new PersistentValue(value);
resources->handles.push_back(unique_ptr<PersistentValue>(handle));
return true;
@@ -262,6 +271,8 @@
std::string GetTypeString() const {
return "send_message";
}
+ private:
+ grpc_byte_buffer *send_message;
};
class SendClientCloseOp : public Op {
diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc
index 9c5d9d2..8cbfb1e 100644
--- a/src/node/ext/call_credentials.cc
+++ b/src/node/ext/call_credentials.cc
@@ -162,6 +162,7 @@
plugin.get_metadata = plugin_get_metadata;
plugin.destroy = plugin_destroy_state;
plugin.state = reinterpret_cast<void*>(state);
+ plugin.type = "";
grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin(
plugin, NULL);
info.GetReturnValue().Set(WrapStruct(creds));
@@ -225,7 +226,7 @@
uv_close((uv_handle_t *)async, (uv_close_cb)free);
}
-void plugin_get_metadata(void *state, const char *service_url,
+void plugin_get_metadata(void *state, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data) {
uv_async_t *async = static_cast<uv_async_t*>(malloc(sizeof(uv_async_t)));
@@ -234,7 +235,7 @@
SendPluginCallback);
plugin_callback_data *data = new plugin_callback_data;
data->state = reinterpret_cast<plugin_state*>(state);
- data->service_url = service_url;
+ data->service_url = context.service_url;
data->cb = cb;
data->user_data = user_data;
async->data = data;
diff --git a/src/node/ext/call_credentials.h b/src/node/ext/call_credentials.h
index 1cd8d8d..a9bfe30 100644
--- a/src/node/ext/call_credentials.h
+++ b/src/node/ext/call_credentials.h
@@ -84,7 +84,7 @@
void *user_data;
} plugin_callback_data;
-void plugin_get_metadata(void *state, const char *service_url,
+void plugin_get_metadata(void *state, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data);
diff --git a/src/objective-c/README.md b/src/objective-c/README.md
index c1d25b9..30d9aad 100644
--- a/src/objective-c/README.md
+++ b/src/objective-c/README.md
@@ -48,8 +48,8 @@
s.version = '0.0.1'
s.license = '...'
- s.ios.deployment_target = '6.0'
- s.osx.deployment_target = '10.8'
+ s.ios.deployment_target = '7.1'
+ s.osx.deployment_target = '10.9'
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
# You can run this command manually if you later change your protos and need to regenerate.
@@ -60,7 +60,7 @@
ms.source_files = "*.pbobjc.{h,m}"
ms.header_mappings_dir = "."
ms.requires_arc = false
- ms.dependency "Protobuf", "~> 3.0.0-alpha-3"
+ ms.dependency "Protobuf", "~> 3.0.0-alpha-4"
end
# The --objcgrpc_out plugin generates a pair of .pbrpc.h/.pbrpc.m files for each .proto file with
@@ -69,7 +69,7 @@
ss.source_files = "*.pbrpc.{h,m}"
ss.header_mappings_dir = "."
ss.requires_arc = true
- ss.dependency "gRPC", "~> 0.5"
+ ss.dependency "gRPC", "~> 0.12"
ss.dependency "#{s.name}/Messages"
end
end
@@ -156,7 +156,7 @@
You need to compile the generated `.pbobjc.*` files (the enums and messages) without ARC support,
and the generated `.pbrpc.*` files (the services) with ARC support. The generated code depends on
-v0.5+ of the Objective-C gRPC runtime library and v3.0.0-alpha-3+ of the Objective-C Protobuf
+v0.12+ of the Objective-C gRPC runtime library and v3.0.0-alpha-4+ of the Objective-C Protobuf
runtime library.
These libraries need to be integrated into your project as described in their respective Podspec
diff --git a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
index d4f8084..5addf26f 100644
--- a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
+++ b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec
@@ -3,8 +3,8 @@
s.version = "0.0.1"
s.license = "New BSD"
- s.ios.deployment_target = "6.0"
- s.osx.deployment_target = "10.8"
+ s.ios.deployment_target = '7.1'
+ s.osx.deployment_target = '10.9'
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.prepare_command = <<-CMD
@@ -22,7 +22,7 @@
ss.source_files = "*.pbrpc.{h,m}"
ss.header_mappings_dir = "."
ss.requires_arc = true
- ss.dependency "gRPC", "~> 0.7"
+ ss.dependency "gRPC", "~> 0.12"
ss.dependency "#{s.name}/Messages"
end
end
diff --git a/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
index 8710753..6ecef05 100644
--- a/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
+++ b/src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
@@ -3,8 +3,8 @@
s.version = "0.0.1"
s.license = "New BSD"
- s.ios.deployment_target = "6.0"
- s.osx.deployment_target = "10.8"
+ s.ios.deployment_target = '7.1'
+ s.osx.deployment_target = '10.9'
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.prepare_command = <<-CMD
@@ -18,14 +18,14 @@
ms.source_files = "*.pbobjc.{h,m}"
ms.header_mappings_dir = "."
ms.requires_arc = false
- ms.dependency "Protobuf", "~> 3.0.0-alpha-3"
+ ms.dependency "Protobuf", "~> 3.0.0-alpha-4"
end
s.subspec "Services" do |ss|
ss.source_files = "*.pbrpc.{h,m}"
ss.header_mappings_dir = "."
ss.requires_arc = true
- ss.dependency "gRPC", "~> 0.5"
+ ss.dependency "gRPC", "~> 0.12"
ss.dependency "#{s.name}/Messages"
end
end
diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh
index 598f4e7..c4fc564 100755
--- a/src/objective-c/tests/run_tests.sh
+++ b/src/objective-c/tests/run_tests.sh
@@ -51,4 +51,5 @@
-scheme AllTests \
-destination name="iPhone 6" \
test \
- | egrep "$XCODEBUILD_FILTER" -
+ | egrep "$XCODEBUILD_FILTER" \
+ | egrep -v "(GPBDictionary|GPBArray)" -
diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb
index 7972272..db9385e 100644
--- a/src/ruby/ext/grpc/extconf.rb
+++ b/src/ruby/ext/grpc/extconf.rb
@@ -94,6 +94,10 @@
end
$CFLAGS << ' -I' + File.join(grpc_root, 'include')
$LDFLAGS << ' -L' + grpc_lib_dir
+ if grpc_config == 'gcov'
+ $CFLAGS << ' -O0 -fprofile-arcs -ftest-coverage'
+ $LDFLAGS << ' -fprofile-arcs -ftest-coverage -rdynamic'
+ end
raise 'gpr not found' unless have_library('gpr', 'gpr_now')
raise 'grpc not found' unless have_library('grpc', 'grpc_channel_destroy')
end
diff --git a/templates/gRPC.podspec.template b/templates/gRPC.podspec.template
index 3885cb3..de5ed7c 100644
--- a/templates/gRPC.podspec.template
+++ b/templates/gRPC.podspec.template
@@ -54,7 +54,7 @@
%>
Pod::Spec.new do |s|
s.name = 'gRPC'
- version = '0.11.2'
+ version = '0.12.0'
s.version = version
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'http://www.grpc.io'
@@ -97,7 +97,7 @@
ss.requires_arc = false
ss.libraries = 'z'
- ss.dependency 'OpenSSL', '~> 1.0.200'
+ ss.dependency 'OpenSSL', '~> 1.0.204.1'
# ss.compiler_flags = '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w'
end
diff --git a/test/core/client_config/lb_policies_test.c b/test/core/client_config/lb_policies_test.c
index 5aa8140..6f218e7 100644
--- a/test/core/client_config/lb_policies_test.c
+++ b/test/core/client_config/lb_policies_test.c
@@ -135,9 +135,8 @@
gpr_log(GPR_INFO, "KILLING SERVER %d", i);
GPR_ASSERT(f->servers[i] != NULL);
grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
- GPR_ASSERT(
- grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000), NULL)
- .type == GRPC_OP_COMPLETE);
+ GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000),
+ NULL).type == GRPC_OP_COMPLETE);
grpc_server_destroy(f->servers[i]);
f->servers[i] = NULL;
}
@@ -203,8 +202,8 @@
if (f->servers[i] == NULL) continue;
grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000),
- n_millis_time(5000), NULL)
- .type == GRPC_OP_COMPLETE);
+ n_millis_time(5000),
+ NULL).type == GRPC_OP_COMPLETE);
grpc_server_destroy(f->servers[i]);
}
grpc_completion_queue_shutdown(f->cq);
@@ -304,8 +303,8 @@
s_idx = -1;
while ((ev = grpc_completion_queue_next(
- f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL))
- .type != GRPC_QUEUE_TIMEOUT) {
+ f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL)).type !=
+ GRPC_QUEUE_TIMEOUT) {
GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
read_tag = ((int)(gpr_intptr)ev.tag);
gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%d",
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 13517b7..ceca56c 100644
--- a/test/core/client_config/set_initial_connect_string_test.c
+++ b/test/core/client_config/set_initial_connect_string_test.c
@@ -66,15 +66,15 @@
static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, int success) {
GPR_ASSERT(success);
- gpr_slice_buffer_move_into(
- &state.temp_incoming_buffer, &state.incoming_buffer);
+ gpr_slice_buffer_move_into(&state.temp_incoming_buffer,
+ &state.incoming_buffer);
if (state.incoming_buffer.length > strlen(magic_connect_string)) {
state.done = 1;
grpc_endpoint_shutdown(exec_ctx, state.tcp);
grpc_endpoint_destroy(exec_ctx, state.tcp);
} else {
- grpc_endpoint_read(
- exec_ctx, state.tcp, &state.temp_incoming_buffer, &on_read);
+ grpc_endpoint_read(exec_ctx, state.tcp, &state.temp_incoming_buffer,
+ &on_read);
}
}
diff --git a/test/core/end2end/tests/hpack_size.c b/test/core/end2end/tests/hpack_size.c
index 297ea8d..997969d 100644
--- a/test/core/end2end/tests/hpack_size.c
+++ b/test/core/end2end/tests/hpack_size.c
@@ -262,9 +262,9 @@
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
- GPR_ASSERT(grpc_completion_queue_pluck(
- f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
- .type == GRPC_OP_COMPLETE);
+ GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
+ GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
+ NULL).type == GRPC_OP_COMPLETE);
grpc_server_destroy(f->server);
f->server = NULL;
}
diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c
index f592f63..4be6957 100644
--- a/test/core/iomgr/fd_posix_test.c
+++ b/test/core/iomgr/fd_posix_test.c
@@ -121,7 +121,7 @@
int success) {
session *se = arg;
server *sv = se->sv;
- grpc_fd_orphan(exec_ctx, se->em_fd, NULL, "a");
+ grpc_fd_orphan(exec_ctx, se->em_fd, NULL, NULL, "a");
gpr_free(se);
/* Start to shutdown listen fd. */
grpc_fd_shutdown(exec_ctx, sv->em_fd);
@@ -177,7 +177,7 @@
int success) {
server *sv = arg;
- grpc_fd_orphan(exec_ctx, sv->em_fd, NULL, "b");
+ grpc_fd_orphan(exec_ctx, sv->em_fd, NULL, NULL, "b");
gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
sv->done = 1;
@@ -294,7 +294,7 @@
static void client_session_shutdown_cb(grpc_exec_ctx *exec_ctx,
void *arg /*client */, int success) {
client *cl = arg;
- grpc_fd_orphan(exec_ctx, cl->em_fd, NULL, "c");
+ grpc_fd_orphan(exec_ctx, cl->em_fd, NULL, NULL, "c");
cl->done = 1;
grpc_pollset_kick(&g_pollset, NULL);
}
@@ -503,7 +503,7 @@
GPR_ASSERT(b.cb_that_ran == second_read_callback);
gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
- grpc_fd_orphan(&exec_ctx, em_fd, NULL, "d");
+ grpc_fd_orphan(&exec_ctx, em_fd, NULL, NULL, "d");
grpc_exec_ctx_finish(&exec_ctx);
destroy_change_data(&a);
destroy_change_data(&b);
diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c
index f676454..9feac93 100644
--- a/test/core/iomgr/tcp_posix_test.c
+++ b/test/core/iomgr/tcp_posix_test.c
@@ -383,6 +383,76 @@
grpc_exec_ctx_finish(&exec_ctx);
}
+void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, int success) {
+ int *done = arg;
+ *done = 1;
+ grpc_pollset_kick(&g_pollset, NULL);
+}
+
+/* Do a read_test, then release fd and try to read/write again. */
+static void release_fd_test(size_t num_bytes, size_t slice_size) {
+ int sv[2];
+ grpc_endpoint *ep;
+ struct read_socket_state state;
+ size_t written_bytes;
+ int fd;
+ gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_closure fd_released_cb;
+ int fd_released_done = 0;
+ grpc_closure_init(&fd_released_cb, &on_fd_released, &fd_released_done);
+
+ gpr_log(GPR_INFO, "Release fd read_test of size %d, slice size %d", num_bytes,
+ slice_size);
+
+ create_sockets(sv);
+
+ ep = grpc_tcp_create(grpc_fd_create(sv[1], "read_test"), slice_size, "test");
+ grpc_endpoint_add_to_pollset(&exec_ctx, ep, &g_pollset);
+
+ written_bytes = fill_socket_partial(sv[0], num_bytes);
+ gpr_log(GPR_INFO, "Wrote %d bytes", written_bytes);
+
+ state.ep = ep;
+ state.read_bytes = 0;
+ state.target_read_bytes = written_bytes;
+ gpr_slice_buffer_init(&state.incoming);
+ grpc_closure_init(&state.read_cb, read_cb, &state);
+
+ grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb);
+
+ gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+ while (state.read_bytes < state.target_read_bytes) {
+ grpc_pollset_worker worker;
+ grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+ gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+ gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+ grpc_exec_ctx_finish(&exec_ctx);
+ gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+ }
+ GPR_ASSERT(state.read_bytes == state.target_read_bytes);
+ gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+
+ gpr_slice_buffer_destroy(&state.incoming);
+ grpc_tcp_destroy_and_release_fd(&exec_ctx, ep, &fd, &fd_released_cb);
+ gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+ while (!fd_released_done) {
+ grpc_pollset_worker worker;
+ grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+ gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+ }
+ gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+ GPR_ASSERT(fd_released_done == 1);
+ GPR_ASSERT(fd == sv[1]);
+ grpc_exec_ctx_finish(&exec_ctx);
+
+ written_bytes = fill_socket_partial(sv[0], num_bytes);
+ drain_socket_blocking(fd, written_bytes, written_bytes);
+ written_bytes = fill_socket_partial(fd, num_bytes);
+ drain_socket_blocking(sv[0], written_bytes, written_bytes);
+ close(fd);
+}
+
void run_tests(void) {
size_t i = 0;
@@ -402,6 +472,8 @@
for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) {
write_test(40320, i);
}
+
+ release_fd_test(100, 8192);
}
static void clean_up(void) {}
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 4cfef7b..b2b7cfd 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -126,6 +126,8 @@
static const char test_service_url[] = "https://foo.com/foo.v1";
static const char other_test_service_url[] = "https://bar.com/bar.v1";
+static const char test_method[] = "ThisIsNotAMethod";
+
/* -- Utils. -- */
static char *test_json_key_str(void) {
@@ -352,9 +354,10 @@
grpc_call_credentials *creds = grpc_google_iam_credentials_create(
test_google_iam_authorization_token, test_google_iam_authority_selector,
NULL);
- grpc_call_credentials_get_request_metadata(&exec_ctx, creds, NULL,
- test_service_url,
- check_google_iam_metadata, creds);
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
+ grpc_call_credentials_get_request_metadata(
+ &exec_ctx, creds, NULL, auth_md_ctx, check_google_iam_metadata, creds);
grpc_exec_ctx_finish(&exec_ctx);
}
@@ -375,10 +378,11 @@
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_call_credentials *creds =
grpc_access_token_credentials_create("blah", NULL);
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) == 0);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, creds, NULL, test_service_url, check_access_token_metadata,
- creds);
+ &exec_ctx, creds, NULL, auth_md_ctx, check_access_token_metadata, creds);
grpc_exec_ctx_finish(&exec_ctx);
}
@@ -430,6 +434,8 @@
static void test_oauth2_google_iam_composite_creds(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
const grpc_call_credentials_array *creds_array;
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
grpc_call_credentials *oauth2_creds = grpc_md_only_test_credentials_create(
"authorization", test_oauth2_bearer_token, 0);
grpc_call_credentials *google_iam_creds = grpc_google_iam_credentials_create(
@@ -450,7 +456,7 @@
GPR_ASSERT(strcmp(creds_array->creds_array[1]->type,
GRPC_CALL_CREDENTIALS_TYPE_IAM) == 0);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, composite_creds, NULL, test_service_url,
+ &exec_ctx, composite_creds, NULL, auth_md_ctx,
check_oauth2_google_iam_composite_metadata, composite_creds);
grpc_exec_ctx_finish(&exec_ctx);
}
@@ -578,12 +584,14 @@
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_call_credentials *compute_engine_creds =
grpc_google_compute_engine_credentials_create(NULL);
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
/* First request: http get should be called. */
grpc_httpcli_set_override(compute_engine_httpcli_get_success_override,
httpcli_post_should_not_be_called);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, compute_engine_creds, NULL, test_service_url,
+ &exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
@@ -591,7 +599,7 @@
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, compute_engine_creds, NULL, test_service_url,
+ &exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_finish(&exec_ctx);
@@ -601,12 +609,14 @@
static void test_compute_engine_creds_failure(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
grpc_call_credentials *compute_engine_creds =
grpc_google_compute_engine_credentials_create(NULL);
grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override,
httpcli_post_should_not_be_called);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, compute_engine_creds, NULL, test_service_url,
+ &exec_ctx, compute_engine_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
grpc_call_credentials_unref(compute_engine_creds);
grpc_httpcli_set_override(NULL, NULL);
@@ -658,6 +668,8 @@
static void test_refresh_token_creds_success(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
grpc_call_credentials *refresh_token_creds =
grpc_google_refresh_token_credentials_create(test_refresh_token_str,
NULL);
@@ -666,7 +678,7 @@
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
refresh_token_httpcli_post_success);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, refresh_token_creds, NULL, test_service_url,
+ &exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
@@ -674,7 +686,7 @@
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, refresh_token_creds, NULL, test_service_url,
+ &exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
@@ -685,13 +697,15 @@
static void test_refresh_token_creds_failure(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
grpc_call_credentials *refresh_token_creds =
grpc_google_refresh_token_credentials_create(test_refresh_token_str,
NULL);
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
refresh_token_httpcli_post_failure);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, refresh_token_creds, NULL, test_service_url,
+ &exec_ctx, refresh_token_creds, NULL, auth_md_ctx,
on_oauth2_creds_get_metadata_failure, (void *)test_user_data);
grpc_call_credentials_unref(refresh_token_creds);
grpc_httpcli_set_override(NULL, NULL);
@@ -774,6 +788,8 @@
static void test_jwt_creds_success(void) {
char *json_key_string = test_json_key_str();
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
grpc_call_credentials *jwt_creds =
grpc_service_account_jwt_access_credentials_create(
json_key_string, grpc_max_auth_token_lifetime, NULL);
@@ -781,7 +797,7 @@
/* First request: jwt_encode_and_sign should be called. */
grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, jwt_creds, NULL, test_service_url,
+ &exec_ctx, jwt_creds, NULL, auth_md_ctx,
on_jwt_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
@@ -789,15 +805,16 @@
grpc_jwt_encode_and_sign_set_override(
encode_and_sign_jwt_should_not_be_called);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, jwt_creds, NULL, test_service_url,
+ &exec_ctx, jwt_creds, NULL, auth_md_ctx,
on_jwt_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
/* Third request: Different service url so jwt_encode_and_sign should be
called again (no caching). */
+ auth_md_ctx.service_url = other_test_service_url;
grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, jwt_creds, NULL, other_test_service_url,
+ &exec_ctx, jwt_creds, NULL, auth_md_ctx,
on_jwt_creds_get_metadata_success, (void *)test_user_data);
grpc_exec_ctx_flush(&exec_ctx);
@@ -809,13 +826,15 @@
static void test_jwt_creds_signing_failure(void) {
char *json_key_string = test_json_key_str();
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
grpc_call_credentials *jwt_creds =
grpc_service_account_jwt_access_credentials_create(
json_key_string, grpc_max_auth_token_lifetime, NULL);
grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, jwt_creds, NULL, test_service_url,
+ &exec_ctx, jwt_creds, NULL, auth_md_ctx,
on_jwt_creds_get_metadata_failure, (void *)test_user_data);
gpr_free(json_key_string);
@@ -886,13 +905,17 @@
static const plugin_metadata plugin_md[] = {{"foo", "bar"}, {"hi", "there"}};
-static void plugin_get_metadata_success(void *state, const char *service_url,
+static void plugin_get_metadata_success(void *state,
+ grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data) {
size_t i;
grpc_metadata md[GPR_ARRAY_SIZE(plugin_md)];
plugin_state *s = (plugin_state *)state;
- GPR_ASSERT(strcmp(service_url, test_service_url) == 0);
+ GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
+ GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
+ GPR_ASSERT(context.channel_auth_context == NULL);
+ GPR_ASSERT(context.reserved == NULL);
*s = PLUGIN_GET_METADATA_CALLED_STATE;
for (i = 0; i < GPR_ARRAY_SIZE(plugin_md); i++) {
memset(&md[i], 0, sizeof(grpc_metadata));
@@ -903,11 +926,15 @@
cb(user_data, md, GPR_ARRAY_SIZE(md), GRPC_STATUS_OK, NULL);
}
-static void plugin_get_metadata_failure(void *state, const char *service_url,
+static void plugin_get_metadata_failure(void *state,
+ grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data) {
plugin_state *s = (plugin_state *)state;
- GPR_ASSERT(strcmp(service_url, test_service_url) == 0);
+ GPR_ASSERT(strcmp(context.service_url, test_service_url) == 0);
+ GPR_ASSERT(strcmp(context.method_name, test_method) == 0);
+ GPR_ASSERT(context.channel_auth_context == NULL);
+ GPR_ASSERT(context.reserved == NULL);
*s = PLUGIN_GET_METADATA_CALLED_STATE;
cb(user_data, NULL, 0, GRPC_STATUS_UNAUTHENTICATED,
"Could not get metadata for plugin.");
@@ -945,6 +972,8 @@
plugin_state state = PLUGIN_INITIAL_STATE;
grpc_metadata_credentials_plugin plugin;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
plugin.state = &state;
plugin.get_metadata = plugin_get_metadata_success;
@@ -953,8 +982,8 @@
creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL);
GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, creds, NULL, test_service_url,
- on_plugin_metadata_received_success, NULL);
+ &exec_ctx, creds, NULL, auth_md_ctx, on_plugin_metadata_received_success,
+ NULL);
GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
grpc_call_credentials_release(creds);
GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
@@ -966,6 +995,8 @@
plugin_state state = PLUGIN_INITIAL_STATE;
grpc_metadata_credentials_plugin plugin;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, NULL,
+ NULL};
plugin.state = &state;
plugin.get_metadata = plugin_get_metadata_failure;
@@ -974,8 +1005,8 @@
creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL);
GPR_ASSERT(state == PLUGIN_INITIAL_STATE);
grpc_call_credentials_get_request_metadata(
- &exec_ctx, creds, NULL, test_service_url,
- on_plugin_metadata_received_failure, NULL);
+ &exec_ctx, creds, NULL, auth_md_ctx, on_plugin_metadata_received_failure,
+ NULL);
GPR_ASSERT(state == PLUGIN_GET_METADATA_CALLED_STATE);
grpc_call_credentials_release(creds);
GPR_ASSERT(state == PLUGIN_DESTROY_CALLED_STATE);
diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c
index fcfe8a6..fb62bf4 100644
--- a/test/core/security/oauth2_utils.c
+++ b/test/core/security/oauth2_utils.c
@@ -80,13 +80,16 @@
oauth2_request request;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_closure do_nothing_closure;
+ grpc_auth_metadata_context null_ctx = {"", "", NULL, NULL};
+
grpc_pollset_init(&request.pollset);
request.is_done = 0;
grpc_closure_init(&do_nothing_closure, do_nothing, NULL);
grpc_call_credentials_get_request_metadata(&exec_ctx, creds, &request.pollset,
- "", on_oauth2_response, &request);
+ null_ctx, on_oauth2_response,
+ &request);
grpc_exec_ctx_finish(&exec_ctx);
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index eb63724..50fe61c 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -74,10 +74,13 @@
synchronizer sync;
grpc_channel_credentials *creds = NULL;
char *service_url = "https://test.foo.google.com/Foo";
+ grpc_auth_metadata_context context;
gpr_cmdline *cl = gpr_cmdline_create("print_google_default_creds_token");
gpr_cmdline_add_string(cl, "service_url",
"Service URL for the token request.", &service_url);
gpr_cmdline_parse(cl, argc, argv);
+ memset(&context, 0, sizeof(context));
+ context.service_url = service_url;
grpc_init();
@@ -93,7 +96,7 @@
grpc_call_credentials_get_request_metadata(
&exec_ctx, ((grpc_composite_channel_credentials *)creds)->call_creds,
- &sync.pollset, service_url, on_metadata_response, &sync);
+ &sync.pollset, context, on_metadata_response, &sync);
gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
while (!sync.is_done) {
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 6da9333..dd02c4a 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -119,10 +119,13 @@
bool IsBlocking() const GRPC_OVERRIDE { return is_blocking_; }
- Status GetMetadata(grpc::string_ref service_url,
+ Status GetMetadata(grpc::string_ref service_url, grpc::string_ref method_name,
+ const grpc::AuthContext& channel_auth_context,
std::multimap<grpc::string, grpc::string>* metadata)
GRPC_OVERRIDE {
EXPECT_GT(service_url.length(), 0UL);
+ EXPECT_GT(method_name.length(), 0UL);
+ EXPECT_TRUE(channel_auth_context.IsPeerAuthenticated());
EXPECT_TRUE(metadata != nullptr);
if (is_successful_) {
metadata->insert(std::make_pair(kMetadataKey, metadata_value_));
diff --git a/tools/jenkins/run_jenkins.sh b/tools/jenkins/run_jenkins.sh
index 0e1af2a..4bb6c39 100755
--- a/tools/jenkins/run_jenkins.sh
+++ b/tools/jenkins/run_jenkins.sh
@@ -63,7 +63,7 @@
# Prevent msbuild from picking up "platform" env variable, which would break the build
unset platform
- python tools/run_tests/run_tests.py -t -l $language -x report.xml $@ || true
+ python tools/run_tests/run_tests.py -t -l $language -c $config -x report.xml $@ || true
elif [ "$platform" == "macos" ]
then
@@ -77,11 +77,6 @@
MAKE=gmake ./tools/run_tests/run_tests.py -t -l $language -c $config -x report.xml $@ || true
-elif [ "$platform" == "interop" ]
-then
- echo "building interop tests for language $language"
-
- ./tools/run_tests/run_interop_tests.py --use_docker -t -l $language --cloud_to_prod --server all || true
else
echo "Unknown platform $platform"
exit 1
diff --git a/tools/run_tests/post_tests_ruby.sh b/tools/run_tests/post_tests_ruby.sh
new file mode 100755
index 0000000..66a9fbc
--- /dev/null
+++ b/tools/run_tests/post_tests_ruby.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+if [ "$CONFIG" != "gcov" ] ; then exit ; fi
+
+root=$(readlink -f $(dirname $0)/../..)
+out=$root/reports/ruby_ext_coverage
+tmp1=$(mktemp)
+tmp2=$(mktemp)
+cd $root
+lcov --capture --directory . --output-file $tmp1
+lcov --extract $tmp1 "$root/src/ruby/*" --output-file $tmp2
+genhtml $tmp2 --output-directory $out
+rm $tmp2
+rm $tmp1
+
+cp -rv $root/src/ruby/coverage $root/reports/ruby
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 2d12ade..f1595ac 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -322,7 +322,7 @@
return [['tools/run_tests/build_ruby.sh']]
def post_tests_steps(self):
- return []
+ return [['tools/run_tests/post_tests_ruby.sh']]
def makefile_name(self):
return 'Makefile'
@@ -862,6 +862,7 @@
port_server_port = 32767
_start_port_server(port_server_port)
resultset = None
+ num_test_failures = 0
try:
infinite_runs = runs_per_test == 0
one_run = set(
@@ -885,7 +886,7 @@
else itertools.repeat(massaged_one_run, runs_per_test))
all_runs = itertools.chain.from_iterable(runs_sequence)
- number_failures, resultset = jobset.run(
+ num_test_failures, resultset = jobset.run(
all_runs, check_cancelled, newline_on_success=newline_on_success,
travis=args.travis, infinite_runs=infinite_runs, maxjobs=args.jobs,
stop_on_failure=args.stop_on_failure,
@@ -902,8 +903,6 @@
do_newline=True)
else:
jobset.message('PASSED', k, do_newline=True)
- if number_failures:
- return 2
finally:
for antagonist in antagonists:
antagonist.kill()
@@ -913,8 +912,8 @@
number_failures, _ = jobset.run(
post_tests_steps, maxjobs=1, stop_on_failure=True,
newline_on_success=newline_on_success, travis=args.travis)
- if number_failures:
- return 3
+ if num_test_failures or number_failures:
+ return 2
if cache: cache.save()