From 75516068fab61c199701d9ddb7b56c2d11142b1a Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Sat, 7 Mar 2015 15:10:30 -0800 Subject: [PATCH 01/21] Adding refresh token parsing This is the first step for refresh token credentials. --- src/core/security/json_token.c | 79 +++++++++++++++++++++++++--- src/core/security/json_token.h | 23 +++++++- test/core/security/json_token_test.c | 70 ++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 8 deletions(-) diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c index 40b612b2065..eadae336099 100644 --- a/src/core/security/json_token.c +++ b/src/core/security/json_token.c @@ -52,8 +52,9 @@ /* 1 hour max. */ const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0}; -#define GRPC_AUTH_JSON_KEY_TYPE_INVALID "invalid" -#define GRPC_AUTH_JSON_KEY_TYPE_SERVICE_ACCOUNT "service_account" +#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" #define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256" #define GRPC_JWT_TYPE "JWT" @@ -87,7 +88,7 @@ static int set_json_key_string_property(grpc_json *json, const char *prop_name, 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_KEY_TYPE_INVALID); + strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID); } grpc_auth_json_key grpc_auth_json_key_create_from_string( @@ -100,7 +101,7 @@ grpc_auth_json_key grpc_auth_json_key_create_from_string( int success = 0; memset(&result, 0, sizeof(grpc_auth_json_key)); - result.type = GRPC_AUTH_JSON_KEY_TYPE_INVALID; + result.type = GRPC_AUTH_JSON_TYPE_INVALID; if (json == NULL) { gpr_log(GPR_ERROR, "Invalid json string %s", json_string); goto end; @@ -108,10 +109,10 @@ grpc_auth_json_key grpc_auth_json_key_create_from_string( prop_value = json_get_string_property(json, "type"); if (prop_value == NULL || - strcmp(prop_value, GRPC_AUTH_JSON_KEY_TYPE_SERVICE_ACCOUNT)) { + strcmp(prop_value, GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT)) { goto end; } - result.type = GRPC_AUTH_JSON_KEY_TYPE_SERVICE_ACCOUNT; + result.type = GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT; if (!set_json_key_string_property(json, "private_key_id", &result.private_key_id) || @@ -148,7 +149,7 @@ end: void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key) { if (json_key == NULL) return; - json_key->type = GRPC_AUTH_JSON_KEY_TYPE_INVALID; + 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; @@ -331,3 +332,67 @@ 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_string( + const char *json_string) { + grpc_auth_refresh_token result; + char *scratchpad = gpr_strdup(json_string); + grpc_json *json = grpc_json_parse_string(scratchpad); + 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 string %s", json_string); + 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 (json != NULL) grpc_json_destroy(json); + if (!success) grpc_auth_refresh_token_destruct(&result); + 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/security/json_token.h b/src/core/security/json_token.h index 029ede39558..197796ab4cd 100644 --- a/src/core/security/json_token.h +++ b/src/core/security/json_token.h @@ -44,7 +44,7 @@ /* --- auth_json_key parsing. --- */ typedef struct { - char *type; + const char *type; char *private_key_id; char *client_id; char *client_email; @@ -79,4 +79,25 @@ typedef char *(*grpc_jwt_encode_and_sign_override)( 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); + +/* Destructs the object. */ +void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token); + #endif /* GRPC_INTERNAL_CORE_SECURITY_JSON_TOKEN_H */ diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c index ca5b8891023..0f940a1739c 100644 --- a/test/core/security/json_token_test.c +++ b/test/core/security/json_token_test.c @@ -78,6 +78,13 @@ static const char test_json_key_str_part3[] = "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent." "com\", \"type\": \"service_account\" }"; +/* Test refresh token. */ +static const char test_refresh_token_str[] = + "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," + " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," + " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," + " \"type\": \"authorized_user\"}"; + static const char test_scope[] = "myperm1 myperm2"; static const char test_service_url[] = "https://foo.com/foo.v1"; @@ -419,6 +426,64 @@ static void test_jwt_creds_jwt_encode_and_sign(void) { jwt_creds_check_jwt_claim); } +static void test_parse_refresh_token_success(void) { + grpc_auth_refresh_token refresh_token = + grpc_auth_refresh_token_create_from_string(test_refresh_token_str); + GPR_ASSERT(grpc_auth_refresh_token_is_valid(&refresh_token)); + GPR_ASSERT(refresh_token.type != NULL && + !(strcmp(refresh_token.type, "authorized_user"))); + GPR_ASSERT(refresh_token.client_id != NULL && + !(strcmp(refresh_token.client_id, + "32555999999.apps.googleusercontent.com"))); + GPR_ASSERT( + refresh_token.client_secret != NULL && + !(strcmp(refresh_token.client_secret, "EmssLNjJy1332hD4KFsecret"))); + GPR_ASSERT(refresh_token.refresh_token != NULL && + !(strcmp(refresh_token.refresh_token, + "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42"))); + grpc_auth_refresh_token_destruct(&refresh_token); +} + +static void test_parse_refresh_token_failure_no_type(void) { + const char refresh_token_str[] = + "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," + " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," + " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"}"; + grpc_auth_refresh_token refresh_token = + grpc_auth_refresh_token_create_from_string(refresh_token_str); + GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); +} + +static void test_parse_refresh_token_failure_no_client_id(void) { + const char refresh_token_str[] = + "{ \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," + " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," + " \"type\": \"authorized_user\"}"; + grpc_auth_refresh_token refresh_token = + grpc_auth_refresh_token_create_from_string(refresh_token_str); + GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); +} + +static void test_parse_refresh_token_failure_no_client_secret(void) { + const char refresh_token_str[] = + "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," + " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"," + " \"type\": \"authorized_user\"}"; + grpc_auth_refresh_token refresh_token = + grpc_auth_refresh_token_create_from_string(refresh_token_str); + GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); +} + +static void test_parse_refresh_token_failure_no_refresh_token(void) { + const char refresh_token_str[] = + "{ \"client_id\": \"32555999999.apps.googleusercontent.com\"," + " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\"," + " \"type\": \"authorized_user\"}"; + grpc_auth_refresh_token refresh_token = + grpc_auth_refresh_token_create_from_string(refresh_token_str); + GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token)); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); test_parse_json_key_success(); @@ -430,5 +495,10 @@ int main(int argc, char **argv) { test_parse_json_key_failure_no_private_key(); test_service_account_creds_jwt_encode_and_sign(); test_jwt_creds_jwt_encode_and_sign(); + test_parse_refresh_token_success(); + test_parse_refresh_token_failure_no_type(); + test_parse_refresh_token_failure_no_client_id(); + test_parse_refresh_token_failure_no_client_secret(); + test_parse_refresh_token_failure_no_refresh_token(); return 0; } From 3371cdf918a153674eff3e0e446ab77d8f7234a5 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Mon, 9 Mar 2015 10:32:19 -0700 Subject: [PATCH 02/21] Fixing !strcmp in the tests. --- test/core/security/json_token_test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c index 0f940a1739c..b43e0425ee2 100644 --- a/test/core/security/json_token_test.c +++ b/test/core/security/json_token_test.c @@ -431,16 +431,16 @@ static void test_parse_refresh_token_success(void) { grpc_auth_refresh_token_create_from_string(test_refresh_token_str); GPR_ASSERT(grpc_auth_refresh_token_is_valid(&refresh_token)); GPR_ASSERT(refresh_token.type != NULL && - !(strcmp(refresh_token.type, "authorized_user"))); + (strcmp(refresh_token.type, "authorized_user") == 0)); GPR_ASSERT(refresh_token.client_id != NULL && - !(strcmp(refresh_token.client_id, - "32555999999.apps.googleusercontent.com"))); + (strcmp(refresh_token.client_id, + "32555999999.apps.googleusercontent.com") == 0)); GPR_ASSERT( refresh_token.client_secret != NULL && - !(strcmp(refresh_token.client_secret, "EmssLNjJy1332hD4KFsecret"))); + (strcmp(refresh_token.client_secret, "EmssLNjJy1332hD4KFsecret") == 0)); GPR_ASSERT(refresh_token.refresh_token != NULL && - !(strcmp(refresh_token.refresh_token, - "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42"))); + (strcmp(refresh_token.refresh_token, + "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42") == 0)); grpc_auth_refresh_token_destruct(&refresh_token); } From b0829ebaf174216787c9a9557cf4a40afa2c8023 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 3 Mar 2015 09:30:55 -0800 Subject: [PATCH 03/21] C# server side TLS support --- include/grpc/grpc_security.h | 3 +- src/csharp/Grpc.Core/Grpc.Core.csproj | 2 + .../Internal/ServerCredentialsSafeHandle.cs | 68 +++++++++++ .../Grpc.Core/Internal/ServerSafeHandle.cs | 9 +- src/csharp/Grpc.Core/Server.cs | 12 +- src/csharp/Grpc.Core/ServerCredentials.cs | 107 ++++++++++++++++++ .../Grpc.IntegrationTesting.csproj | 1 + .../Grpc.IntegrationTesting/InteropClient.cs | 13 +-- .../InteropClientServerTest.cs | 8 +- .../Grpc.IntegrationTesting/InteropServer.cs | 12 +- .../TestCredentials.cs | 83 ++++++++++++++ src/csharp/ext/grpc_csharp_ext.c | 35 ++++++ 12 files changed, 334 insertions(+), 19 deletions(-) create mode 100644 src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/ServerCredentials.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/TestCredentials.cs diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index ab2cc08489d..c297622a512 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -167,10 +167,9 @@ grpc_server_credentials *grpc_ssl_server_credentials_create( grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( void); -/* --- Secure server creation. --- */ +/* --- Server-side secure ports. --- */ /* Add a HTTP2 over an encrypted link over tcp listener. - Server must have been created with grpc_secure_server_create. Returns bound port number on success, 0 on failure. REQUIRES: server not started */ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 78b6cdde59b..c4b12b1cab0 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -74,6 +74,8 @@ + + diff --git a/src/csharp/Grpc.Core/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs similarity index 99% rename from src/csharp/Grpc.Core/ServerCallHandler.cs rename to src/csharp/Grpc.Core/Internal/ServerCallHandler.cs index c5598e5e994..25fd4fab8f7 100644 --- a/src/csharp/Grpc.Core/ServerCallHandler.cs +++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs @@ -36,7 +36,7 @@ using System.Linq; using Grpc.Core.Internal; using Grpc.Core.Utils; -namespace Grpc.Core +namespace Grpc.Core.Internal { internal interface IServerCallHandler { diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs index 9c9dfa4bc9b..e73e7b762ef 100644 --- a/src/csharp/Grpc.Core/Marshaller.cs +++ b/src/csharp/Grpc.Core/Marshaller.cs @@ -66,6 +66,9 @@ namespace Grpc.Core } } + /// + /// Utilities for creating marshallers. + /// public static class Marshallers { public static Marshaller Create(Func serializer, Func deserializer) diff --git a/src/csharp/Grpc.Core/RpcException.cs b/src/csharp/Grpc.Core/RpcException.cs index 0356bf7b4a9..433d87215ee 100644 --- a/src/csharp/Grpc.Core/RpcException.cs +++ b/src/csharp/Grpc.Core/RpcException.cs @@ -35,6 +35,9 @@ using System; namespace Grpc.Core { + /// + /// Thrown when remote procedure call fails. + /// public class RpcException : Exception { private readonly Status status; diff --git a/src/csharp/Grpc.Core/ServerCalls.cs b/src/csharp/Grpc.Core/ServerCalls.cs index b2dcdf24f6b..dcae99446fe 100644 --- a/src/csharp/Grpc.Core/ServerCalls.cs +++ b/src/csharp/Grpc.Core/ServerCalls.cs @@ -32,6 +32,7 @@ #endregion using System; +using Grpc.Core.Internal; namespace Grpc.Core { diff --git a/src/csharp/Grpc.Core/ServerCredentials.cs b/src/csharp/Grpc.Core/ServerCredentials.cs index 59c341ef51f..ab7d0b49143 100644 --- a/src/csharp/Grpc.Core/ServerCredentials.cs +++ b/src/csharp/Grpc.Core/ServerCredentials.cs @@ -33,10 +33,14 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using Grpc.Core.Internal; namespace Grpc.Core { + /// + /// Server side credentials. + /// public abstract class ServerCredentials { /// @@ -51,8 +55,8 @@ namespace Grpc.Core /// public class KeyCertificatePair { - string certChain; - string privateKey; + readonly string certChain; + readonly string privateKey; public KeyCertificatePair(string certChain, string privateKey) { @@ -82,10 +86,9 @@ namespace Grpc.Core /// public class SslServerCredentials : ServerCredentials { - // TODO: immutable list... - List keyCertPairs; + ImmutableList keyCertPairs; - public SslServerCredentials(List keyCertPairs) + public SslServerCredentials(ImmutableList keyCertPairs) { this.keyCertPairs = keyCertPairs; } diff --git a/src/csharp/Grpc.Core/ServerServiceDefinition.cs b/src/csharp/Grpc.Core/ServerServiceDefinition.cs index d7f69f3c9f3..004415477ca 100644 --- a/src/csharp/Grpc.Core/ServerServiceDefinition.cs +++ b/src/csharp/Grpc.Core/ServerServiceDefinition.cs @@ -33,22 +33,26 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; +using Grpc.Core.Internal; namespace Grpc.Core { + /// + /// Mapping of method names to server call handlers. + /// public class ServerServiceDefinition { readonly string serviceName; - // TODO: we would need an immutable dictionary here... - readonly Dictionary callHandlers; + readonly ImmutableDictionary callHandlers; - private ServerServiceDefinition(string serviceName, Dictionary callHandlers) + private ServerServiceDefinition(string serviceName, ImmutableDictionary callHandlers) { this.serviceName = serviceName; - this.callHandlers = new Dictionary(callHandlers); + this.callHandlers = callHandlers; } - internal Dictionary CallHandlers + internal ImmutableDictionary CallHandlers { get { @@ -89,7 +93,7 @@ namespace Grpc.Core public ServerServiceDefinition Build() { - return new ServerServiceDefinition(serviceName, callHandlers); + return new ServerServiceDefinition(serviceName, callHandlers.ToImmutableDictionary()); } } } diff --git a/src/csharp/Grpc.Core/StatusCode.cs b/src/csharp/Grpc.Core/StatusCode.cs index 111863a2a9c..a9696fa4690 100644 --- a/src/csharp/Grpc.Core/StatusCode.cs +++ b/src/csharp/Grpc.Core/StatusCode.cs @@ -35,9 +35,9 @@ using System; namespace Grpc.Core { - // TODO: element names should changed to comply with C# naming conventions. /// - /// based on grpc_status_code from grpc/status.h + /// Result of a remote procedure call. + /// Based on grpc_status_code from grpc/status.h /// public enum StatusCode { diff --git a/src/csharp/Grpc.Core/packages.config b/src/csharp/Grpc.Core/packages.config new file mode 100644 index 00000000000..cf711ac3622 --- /dev/null +++ b/src/csharp/Grpc.Core/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index 438bf9e95de..cfb258711ad 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -39,6 +39,10 @@ ..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll + + False + ..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + @@ -76,8 +80,5 @@ PreserveNewest - - - - - + + \ No newline at end of file diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index 56760ecdabc..6b92d3c660f 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -109,7 +109,7 @@ namespace Grpc.IntegrationTesting ChannelArgs channelArgs = null; if (!string.IsNullOrEmpty(options.serverHostOverride)) { - channelArgs = ChannelArgs.NewBuilder() + channelArgs = ChannelArgs.CreateBuilder() .AddString(ChannelArgs.SslTargetNameOverrideKey, options.serverHostOverride).Build(); } diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs index 36c784e28f1..814f6311f23 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs @@ -62,7 +62,7 @@ namespace Grpc.IntegrationTesting int port = server.AddPort(host + ":0", TestCredentials.CreateTestServerCredentials()); server.Start(); - var channelArgs = ChannelArgs.NewBuilder() + var channelArgs = ChannelArgs.CreateBuilder() .AddString(ChannelArgs.SslTargetNameOverrideKey, TestCredentials.DefaultHostOverride).Build(); channel = new Channel(host + ":" + port, TestCredentials.CreateTestClientCredentials(true), channelArgs); diff --git a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs index 10df704f1dd..401c50b1aea 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs @@ -33,6 +33,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.IO; using System.Text.RegularExpressions; @@ -77,7 +78,7 @@ namespace Grpc.IntegrationTesting var keyCertPair = new KeyCertificatePair( File.ReadAllText(ServerCertChainPath), File.ReadAllText(ServerPrivateKeyPath)); - return new SslServerCredentials(new List { keyCertPair }); + return new SslServerCredentials(ImmutableList.Create(keyCertPair)); } } } diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config index 51c17bcd5e7..157c264eac0 100644 --- a/src/csharp/Grpc.IntegrationTesting/packages.config +++ b/src/csharp/Grpc.IntegrationTesting/packages.config @@ -2,4 +2,5 @@ + \ No newline at end of file From 8a929a965b89251ac54ad0bf9beb0a8f0a7d2258 Mon Sep 17 00:00:00 2001 From: Xiaoguang Sun Date: Fri, 13 Mar 2015 14:22:31 +0800 Subject: [PATCH 19/21] Fix duplicated symbols Fix duplicated symbols caused by having definition instead of declaration in header file. --- src/php/ext/grpc/call.c | 2 ++ src/php/ext/grpc/call.h | 2 +- src/php/ext/grpc/channel.c | 2 ++ src/php/ext/grpc/channel.h | 2 +- src/php/ext/grpc/completion_queue.c | 2 ++ src/php/ext/grpc/completion_queue.h | 2 +- src/php/ext/grpc/credentials.c | 2 ++ src/php/ext/grpc/credentials.h | 2 +- src/php/ext/grpc/server.c | 2 ++ src/php/ext/grpc/server.h | 2 +- src/php/ext/grpc/server_credentials.c | 2 ++ src/php/ext/grpc/server_credentials.h | 2 +- src/php/ext/grpc/timeval.c | 2 ++ src/php/ext/grpc/timeval.h | 2 +- 14 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c index df0635dc727..798747109a1 100644 --- a/src/php/ext/grpc/call.c +++ b/src/php/ext/grpc/call.c @@ -56,6 +56,8 @@ #include "completion_queue.h" #include "byte_buffer.h" +zend_class_entry *grpc_ce_call; + /* Frees and destroys an instance of wrapped_grpc_call */ void free_wrapped_grpc_call(void *object TSRMLS_DC) { wrapped_grpc_call *call = (wrapped_grpc_call *)object; diff --git a/src/php/ext/grpc/call.h b/src/php/ext/grpc/call.h index 827e9a27a87..bce5d82974f 100644 --- a/src/php/ext/grpc/call.h +++ b/src/php/ext/grpc/call.h @@ -57,7 +57,7 @@ } while (0) /* Class entry for the Call PHP class */ -zend_class_entry *grpc_ce_call; +extern zend_class_entry *grpc_ce_call; /* Wrapper struct for grpc_call that can be associated with a PHP object */ typedef struct wrapped_grpc_call { diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c index d6296f94130..5e99332fab8 100644 --- a/src/php/ext/grpc/channel.c +++ b/src/php/ext/grpc/channel.c @@ -55,6 +55,8 @@ #include "server.h" #include "credentials.h" +zend_class_entry *grpc_ce_channel; + /* Frees and destroys an instance of wrapped_grpc_channel */ void free_wrapped_grpc_channel(void *object TSRMLS_DC) { wrapped_grpc_channel *channel = (wrapped_grpc_channel *)object; diff --git a/src/php/ext/grpc/channel.h b/src/php/ext/grpc/channel.h index f426a25cafc..2c79668a4d8 100755 --- a/src/php/ext/grpc/channel.h +++ b/src/php/ext/grpc/channel.h @@ -46,7 +46,7 @@ #include "grpc/grpc.h" /* Class entry for the PHP Channel class */ -zend_class_entry *grpc_ce_channel; +extern zend_class_entry *grpc_ce_channel; /* Wrapper struct for grpc_channel that can be associated with a PHP object */ typedef struct wrapped_grpc_channel { diff --git a/src/php/ext/grpc/completion_queue.c b/src/php/ext/grpc/completion_queue.c index 30c871b0783..93abf5df36b 100644 --- a/src/php/ext/grpc/completion_queue.c +++ b/src/php/ext/grpc/completion_queue.c @@ -52,6 +52,8 @@ #include "event.h" #include "timeval.h" +zend_class_entry *grpc_ce_completion_queue; + /* Frees and destroys a wrapped instance of grpc_completion_queue */ void free_wrapped_grpc_completion_queue(void *object TSRMLS_DC) { wrapped_grpc_completion_queue *queue = NULL; diff --git a/src/php/ext/grpc/completion_queue.h b/src/php/ext/grpc/completion_queue.h index 6ce1df7c8cd..1d386cc58f4 100755 --- a/src/php/ext/grpc/completion_queue.h +++ b/src/php/ext/grpc/completion_queue.h @@ -46,7 +46,7 @@ #include "grpc/grpc.h" /* Class entry for the PHP CompletionQueue class */ -zend_class_entry *grpc_ce_completion_queue; +extern zend_class_entry *grpc_ce_completion_queue; /* Wrapper class for grpc_completion_queue that can be associated with a PHP object */ diff --git a/src/php/ext/grpc/credentials.c b/src/php/ext/grpc/credentials.c index 6d8f59fa33d..a94b0eac2d3 100644 --- a/src/php/ext/grpc/credentials.c +++ b/src/php/ext/grpc/credentials.c @@ -49,6 +49,8 @@ #include "grpc/grpc.h" #include "grpc/grpc_security.h" +zend_class_entry *grpc_ce_credentials; + /* Frees and destroys an instance of wrapped_grpc_credentials */ void free_wrapped_grpc_credentials(void *object TSRMLS_DC) { wrapped_grpc_credentials *creds = (wrapped_grpc_credentials *)object; diff --git a/src/php/ext/grpc/credentials.h b/src/php/ext/grpc/credentials.h index 3ff75af9dbe..86d7ae5b144 100755 --- a/src/php/ext/grpc/credentials.h +++ b/src/php/ext/grpc/credentials.h @@ -47,7 +47,7 @@ #include "grpc/grpc_security.h" /* Class entry for the Credentials PHP class */ -zend_class_entry *grpc_ce_credentials; +extern zend_class_entry *grpc_ce_credentials; /* Wrapper struct for grpc_credentials that can be associated with a PHP * object */ diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c index 00d08c6ecf0..a5cfd952871 100644 --- a/src/php/ext/grpc/server.c +++ b/src/php/ext/grpc/server.c @@ -56,6 +56,8 @@ #include "channel.h" #include "server_credentials.h" +zend_class_entry *grpc_ce_server; + /* Frees and destroys an instance of wrapped_grpc_server */ void free_wrapped_grpc_server(void *object TSRMLS_DC) { wrapped_grpc_server *server = (wrapped_grpc_server *)object; diff --git a/src/php/ext/grpc/server.h b/src/php/ext/grpc/server.h index ecef4c64299..b55689c5816 100755 --- a/src/php/ext/grpc/server.h +++ b/src/php/ext/grpc/server.h @@ -46,7 +46,7 @@ #include "grpc/grpc.h" /* Class entry for the Server PHP class */ -zend_class_entry *grpc_ce_server; +extern zend_class_entry *grpc_ce_server; /* Wrapper struct for grpc_server that can be associated with a PHP object */ typedef struct wrapped_grpc_server { diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c index 8aaa86ce947..df64e659869 100644 --- a/src/php/ext/grpc/server_credentials.c +++ b/src/php/ext/grpc/server_credentials.c @@ -49,6 +49,8 @@ #include "grpc/grpc.h" #include "grpc/grpc_security.h" +zend_class_entry *grpc_ce_server_credentials; + /* Frees and destroys an instace of wrapped_grpc_server_credentials */ void free_wrapped_grpc_server_credentials(void *object TSRMLS_DC) { wrapped_grpc_server_credentials *creds = diff --git a/src/php/ext/grpc/server_credentials.h b/src/php/ext/grpc/server_credentials.h index ce2a4da138c..8ed36971506 100755 --- a/src/php/ext/grpc/server_credentials.h +++ b/src/php/ext/grpc/server_credentials.h @@ -47,7 +47,7 @@ #include "grpc/grpc_security.h" /* Class entry for the Server_Credentials PHP class */ -zend_class_entry *grpc_ce_server_credentials; +extern zend_class_entry *grpc_ce_server_credentials; /* Wrapper struct for grpc_server_credentials that can be associated with a PHP * object */ diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c index 5b0142cbe47..f90f0062bab 100644 --- a/src/php/ext/grpc/timeval.c +++ b/src/php/ext/grpc/timeval.c @@ -50,6 +50,8 @@ #include "grpc/grpc.h" #include "grpc/support/time.h" +zend_class_entry *grpc_ce_timeval; + /* Frees and destroys an instance of wrapped_grpc_call */ void free_wrapped_grpc_timeval(void *object TSRMLS_DC) { efree(object); } diff --git a/src/php/ext/grpc/timeval.h b/src/php/ext/grpc/timeval.h index 0e215fc8848..e3183f691db 100755 --- a/src/php/ext/grpc/timeval.h +++ b/src/php/ext/grpc/timeval.h @@ -47,7 +47,7 @@ #include "grpc/support/time.h" /* Class entry for the Timeval PHP Class */ -zend_class_entry *grpc_ce_timeval; +extern zend_class_entry *grpc_ce_timeval; /* Wrapper struct for timeval that can be associated with a PHP object */ typedef struct wrapped_grpc_timeval { From 5d85675b56477b201fe0ef30e04e52a67e46f66c Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Fri, 13 Mar 2015 13:47:00 +0100 Subject: [PATCH 20/21] Fix port selection for server Commit 31e65be introduces a bug which causes starting server on a randomly selected port. --- src/python/src/grpc/early_adopter/implementations.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python/src/grpc/early_adopter/implementations.py b/src/python/src/grpc/early_adopter/implementations.py index 1c02f9e4d63..6fe90594a74 100644 --- a/src/python/src/grpc/early_adopter/implementations.py +++ b/src/python/src/grpc/early_adopter/implementations.py @@ -71,7 +71,8 @@ class _Server(interfaces.Server): _ONE_DAY_IN_SECONDS) self._fore_link = _fore.ForeLink( self._pool, self._breakdown.request_deserializers, - self._breakdown.response_serializers, None, self._key_chain_pairs) + 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() From 1cbf8d7f16ef43fa9d8a6ce12a0ce8432f01688f Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Fri, 13 Mar 2015 23:59:40 +0900 Subject: [PATCH 21/21] Update doc as requested in review --- src/core/transport/chttp2_transport.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 5cc8375d659..2b15b2a8128 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -1655,6 +1655,12 @@ static int process_read(transport *t, gpr_slice slice) { if (!init_frame_parser(t)) { return 0; } + /* t->last_incoming_stream_id is used as last-stream-id when + sending GOAWAY frame. + https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8 + says that last-stream-id is peer-initiated stream ID. So, + since we don't have server pushed streams, client should send + GOAWAY last-stream-id=0 in this case. */ if (!t->is_client) { t->last_incoming_stream_id = t->incoming_stream_id; }