aboutsummaryrefslogtreecommitdiffhomepage
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/PROTOCOL-HTTP2.md192
-rw-r--r--doc/grpc-auth-support.md289
-rw-r--r--doc/interop-test-descriptions.md204
3 files changed, 684 insertions, 1 deletions
diff --git a/doc/PROTOCOL-HTTP2.md b/doc/PROTOCOL-HTTP2.md
new file mode 100644
index 0000000000..d3fbb60d60
--- /dev/null
+++ b/doc/PROTOCOL-HTTP2.md
@@ -0,0 +1,192 @@
+# gRPC over HTTP2
+
+## Introduction
+This document serves as a detailed description for an implementation of gRPC carried over HTTP2 draft 17 framing. It assumes familiarity with the HTTP2 specification.
+
+## Protocol
+Production rules are using <a href="http://tools.ietf.org/html/rfc5234">ABNF syntax</a>.
+
+### Outline
+
+The following is the general sequence of message atoms in a GRPC request & response message stream
+
+* Request → Request-Headers *Delimited-Message EOS
+* Response → (Response-Headers *Delimited-Message Trailers) / Trailers-Only
+
+
+### Requests
+
+* Request → Request-Headers *Delimited-Message EOS
+
+Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
+
+* **Request-Headers** → Call-Definition *Custom-Metadata
+* **Call-Definition** → Method Scheme Path TE [Authority] [Timeout] [Content-Type] [Message-Type] [Message-Encoding] [Message-Accept-Encoding] [User-Agent]
+* **Method** → “:method POST”
+* **Scheme** → “:scheme ” (“http” / “https”)
+* **Path** → “:path” {_path identifying method within exposed API_}
+* **Authority** → “:authority” {_virtual host name of authority_}
+* **TE** → “te” “trailers” # Used to detect incompatible proxies
+* **Timeout** → “grpc-timeout” TimeoutValue TimeoutUnit
+* **TimeoutValue** → {_positive integer as ASCII string of at most 8 digits_}
+* **TimeoutUnit** → Hour / Minute / Second / Millisecond / Microsecond / Nanosecond
+* **Hour** → “H”
+* **Minute** → “M”
+* **Second** → “S”
+* **Millisecond** → “m”
+* **Microsecond** → “u”
+* **Nanosecond** → “n”
+* **Content-Type** → “content-type” “application/grpc” [(“+proto” / “+json” / {_custom_})]
+* **Content-Coding** → “gzip” / “deflate” / “snappy” / {_custom_}
+* **Message-Encoding** → “grpc-encoding” Content-Coding
+* **Message-Accept-Encoding** → “grpc-accept-encoding” Content-Coding *("," Content-Coding)
+* **User-Agent** → “user-agent” {_structured user-agent string_}
+* **Message-Type** → “grpc-message-type” {_type name for message schema_}
+* **Custom-Metadata** → Binary-Header / ASCII-Header
+* **Binary-Header** → {lowercase ASCII header name ending in “-bin” } {_base64 encoded value_}
+* **ASCII-Header** → {lowercase ASCII header name} {_value_}
+
+
+HTTP2 requires that reserved headers, ones starting with “:” appear before all other headers. Additionally implementations should send **Timeout** immediately after the reserved headers and they should send the **Call-Definition** headers before sending **Custom-Metadata**.
+
+If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements.
+
+**Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Aside from transport limits on the total length of HTTP2 HEADERS the only other constraint is that header names starting with “grpc-” are reserved for future use.
+
+Note that HTTP2 does not allow arbitrary octet sequences for header values so binary header values must be encoded using Base64 as per https://tools.ietf.org/html/rfc4648#section-4. Implementations MUST accept padded and un-padded values and should emit un-padded values. Applications define binary headers by having their names end with “-bin”. Runtime libraries use this suffix to detect binary headers and properly apply base64 encoding & decoding as headers are sent and received.
+
+The repeated sequence of **Delimited-Message** items is delivered in DATA frames
+
+* **Delimited-Message** → Compressed-Flag Message-Length Message
+* **Compressed-Flag** → 0 / 1 # encoded as 1 byte unsigned integer
+* **Message-Length** → {_length of Message_} # encoded as 4 byte unsigned integer
+* **Message** → *{binary octet}
+
+A **Compressed-Flag** value of 1 indicates that the binary octet sequence of **Message** is compressed using the mechanism declared by the **Message-Encoding** header. A value of 0 indicates that no encoding of **Message** bytes has occurred. Compression contexts are NOT maintained over message boundaries, implementations must create a new context for each message in the stream. If the **Message-Encoding** header is omitted then the **Compressed-Flag** must be 0.
+
+For requests, **EOS** (end-of-stream) is indicated by the presence of the END_STREAM flag on the last received DATA frame. In scenarios where the **Request** stream needs to be closed but no data remains to be sent implementations MUST send an empty DATA frame with this flag set.
+
+###Responses
+
+* **Response** → (Response-Headers *Delimited-Message Trailers) / Trailers-Only
+* **Response-Headers** → HTTP-Status [Message-Encoding] [Message-Accept-Encoding] Content-Type *Custom-Metadata
+* **Trailers-Only** → HTTP-Status Content-Type Trailers
+* **Trailers** → Status [Status-Message] *Custom-Metadata
+* **HTTP-Status** → “:status 200”
+* **Status** → “grpc-status” <status-code-as-ASCII-string>
+* **Status-Message** → “grpc-message” <descriptive text for status as ASCII string>
+
+**Response-Headers** & **Trailers-Only** are each delivered in a single HTTP2 HEADERS frame block. Most responses are expected to have both headers and trailers but **Trailers-Only** is permitted for calls that produce an immediate error. Status must be sent in **Trailers** even if the status code is OK.
+
+For responses end-of-stream is indicated by the presence of the END_STREAM flag on the last received HEADERS frame that carries **Trailers**.
+
+Implementations should expect broken deployments to send non-200 HTTP status codes in responses as well as a variety of non-GRPC content-types and to omit **Status** & **Status-Message**. Implementations must synthesize a **Status** & **Status-Message** to propagate to the application layer when this occurs.
+
+####Example
+
+Sample unary-call showing HTTP2 framing sequence
+
+**Request**
+
+```
+HEADERS (flags = END_HEADERS)
+:method = POST
+:scheme = http
+:path = /google.pubsub.v2.PublisherService/CreateTopic
+:authority = pubsub.googleapis.com
+grpc-timeout = 1S
+content-type = application/grpc+proto
+grpc-encoding = gzip
+authorization = Bearer y235.wef315yfh138vh31hv93hv8h3v
+
+DATA (flags = END_STREAM)
+<Delimited Message>
+```
+**Response**
+```
+HEADERS (flags = END_HEADERS)
+:status = 200
+grpc-encoding = gzip
+
+DATA
+<Delimited Message>
+
+HEADERS (flags = END_STREAM, END_HEADERS)
+grpc-status = 0 # OK
+trace-proto-bin = jher831yy13JHy3hc
+```
+####User Agents
+
+While the protocol does not require a user-agent to function it is recommended that clients provide a structured user-agent string that provides a basic description of the calling library, version & platform to facilitate issue diagnosis in heterogeneous environments. The following structure is recommended to library developers
+```
+User-Agent → “grpc-” Language ?(“-” Variant) “/” Version ?( “ (“ *(AdditionalProperty “;”) “)” )
+```
+E.g.
+
+```
+grpc-java/1.2.3
+grpc-ruby/1.2.3
+grpc-ruby-jruby/1.3.4
+grpc-java-android/0.9.1 (gingerbread/1.2.4; nexus5; tmobile)
+```
+####HTTP2 Transport Mapping
+
+#####Stream Identification
+All GRPC calls need to specify an internal ID. We will use HTTP2 stream-ids as call identifiers in this scheme. NOTE: These id’s are contextual to an open HTTP2 session and will not be unique within a given process that is handling more than one HTTP2 session nor can they be used as GUIDs.
+
+#####Data Frames
+DATA frame boundaries have no relation to **Delimited-Message** boundaries and implementations should make no assumptions about their alignment.
+
+#####Errors
+
+When an application or runtime error occurs during an RPC a **Status** and **Status-Message** are delivered in **Trailers**.
+
+In some cases it is possible that the framing of the message stream has become corrupt and the RPC runtime will choose to use an **RST_STREAM** frame to indicate this state to its peer. RPC runtime implementations should interpret RST_STREAM as immediate full-closure of the stream and should propagate an error up to the calling application layer.
+
+The following mapping from RST_STREAM error codes to GRPC error codes is applied.
+
+HTTP2 Code|GRPC Code
+----------|-----------
+NO_ERROR(0)|INTERNAL - An explicit GRPC status of OK should have been sent but this might be used to aggressively lameduck in some scenarios.
+PROTOCOL_ERROR(1)|INTERNAL
+INTERNAL_ERROR(2)|INTERNAL
+FLOW_CONTROL_ERROR(3)|INTERNAL
+SETTINGS_TIMEOUT(4)|INTERNAL
+STREAM_CLOSED|No mapping as there is no open stream to propagate to. Implementations should log.
+FRAME_SIZE_ERROR|INTERNAL
+REFUSED_STREAM|UNAVAILABLE - Indicates that no processing occurred and the request can be retried, possibly elsewhere.
+CANCEL(8)|Mapped to call cancellation when sent by a client.Mapped to CANCELLED when sent by a server. Note that servers should only use this mechanism when they need to cancel a call but the payload byte sequence is incomplete.
+COMPRESSION_ERROR|INTERNAL
+CONNECT_ERROR|INTERNAL
+ENHANCE_YOUR_CALM|RESOURCE_EXHAUSTED ...with additional error detail provided by runtime to indicate that the exhausted resource is bandwidth.
+INADEQUATE_SECURITY| PERMISSION_DENIED … with additional detail indicating that permission was denied as protocol is not secure enough for call.
+
+
+#####Security
+
+The HTTP2 specification mandates the use of TLS 1.2 or higher when TLS is used with HTTP2. It also places some additional constraints on the allowed ciphers in deployments to avoid known-problems as well as requiring SNI support. It is also expected that HTTP2 will be used in conjunction with proprietary transport security mechanisms about which the specification can make no meaningful recommendations.
+
+#####Connection Management
+######GOAWAY Frame
+Sent by servers to clients to indicate that they will no longer accept any new streams on the associated connections. This frame includes the id of the last successfully accepted stream by the server. Clients should consider any stream initiated after the last successfully accepted stream as UNAVAILABLE and retry the call elsewhere. Clients are free to continue working with the already accepted streams until they complete or the connection is terminated.
+
+Servers should send GOAWAY before terminating a connection to reliably inform clients which work has been accepted by the server and is being executed.
+
+######PING Frame
+Both clients and servers can send a PING frame that the peer must respond to by precisely echoing what they received. This is used to assert that the connection is still live as well as providing a means to estimate end-to-end latency. If a server initiated PING does not receive a response within the deadline expected by the runtime all outstanding calls on the server will be closed with a CANCELLED status. An expired client initiated PING will cause all calls to be closed with an UNAVAILABLE status. Note that the frequency of PINGs is highly dependent on the network environment, implementations are free to adjust PING frequency based on network and application requirements.
+
+######Connection failure
+If a detectable connection failure occurs on the client all calls will be closed with an UNAVAILABLE status. For servers open calls will be closed with a CANCELLED status.
+
+
+### Appendix A - GRPC for Protobuf
+
+The service interfaces declared by protobuf are easily mapped onto GRPC by code generation extensions to protoc. The following defines the mapping to be used
+
+
+* **Path** → / Service-Name / {_method name_}
+* **Service-Name** → ?( {_proto package name_} "." ) {_service name_}
+* **Message-Type** → {_fully qualified proto message name_}
+* **Content-Type** → "application/grpc+proto"
+
+
diff --git a/doc/grpc-auth-support.md b/doc/grpc-auth-support.md
new file mode 100644
index 0000000000..800fbedd80
--- /dev/null
+++ b/doc/grpc-auth-support.md
@@ -0,0 +1,289 @@
+#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::unique_ptr<Credentials> creds = CredentialsFactory::SslCredentials(ssl_opts);
+// Create a channel using the credentials created in the previous step
+std::shared_ptr<ChannelInterface> channel = CreateChannel(server_name, creds, channel_args);
+// 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::unique_ptr<Credentials> creds = CredentialsFactory::GoogleDefaultCredentials();
+// Create a channel, stub and make RPC calls (same as in the previous example)
+std::shared_ptr<ChannelInterface> channel = CreateChannel(server_name, creds, channel_args);
+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/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md
index 84ceaa3081..98cd5ab4fc 100644
--- a/doc/interop-test-descriptions.md
+++ b/doc/interop-test-descriptions.md
@@ -4,7 +4,7 @@ Interoperability Test Case Descriptions
Client and server use
[test.proto](https://github.com/grpc/grpc/blob/master/test/proto/test.proto)
and the [gRPC over HTTP/2 v2
-protocol](https://github.com/grpc/grpc-common/blob/master/PROTOCOL-HTTP2.md).
+protocol](doc/PROTOCOL-HTTP2.md).
Client
------
@@ -91,6 +91,87 @@ Client asserts:
* clients are free to assert that the response payload body contents are zero
and comparing the entire response message against a golden response
+### large_compressed_unary
+
+This test verifies compressed unary calls succeed in sending messages. It
+sends one unary request for every combination of compression algorithm and
+payload type.
+
+In all scenarios, whether compression was actually performed is determined by
+the compression bit in the response's message flags. The response's compression
+value indicates which algorithm was used if said compression bit is set.
+
+
+Server features:
+* [UnaryCall][]
+* [Compressable Payload][]
+* [Uncompressable Payload][]
+* [Random Payload][]
+
+Procedure:
+ 1. Client calls UnaryCall with:
+
+ ```
+ {
+ response_compression: <one of {NONE, GZIP, DEFLATE}>
+ response_type: COMPRESSABLE
+ response_size: 314159
+ payload:{
+ body: 271828 bytes of zeros
+ }
+ }
+ ```
+ Client asserts:
+ * call was successful
+ * response payload type is COMPRESSABLE
+ * response compression is consistent with the requested one.
+ * if `response_compression == NONE`, the response MUST NOT have the
+ compressed message flag set.
+ * if `response_compression != NONE`, the response MUST have the compressed
+ message flag set.
+ * response payload body is 314159 bytes in size
+ * clients are free to assert that the response payload body contents are
+ zero and comparing the entire response message against a golden response
+
+
+ 2. Client calls UnaryCall with:
+ ```
+ {
+ response_compression: <one of {NONE, GZIP, DEFLATE}>
+ response_type: UNCOMPRESSABLE
+ response_size: 314159
+ payload:{
+ body: 271828 bytes of zeros
+ }
+ }
+ ```
+ Client asserts:
+ * call was successful
+ * response payload type is UNCOMPRESSABLE
+ * response compression is consistent with the requested one.
+ * the response MUST NOT have the compressed message flag set.
+ * response payload body is 314159 bytes in size
+ * clients are free to assert that the response payload body contents are
+ identical to the golden uncompressable data at `test/cpp/interop/rnd.dat`.
+
+
+ 3. Client calls UnaryCall with:
+ ```
+ {
+ response_compression: <one of {NONE, GZIP, DEFLATE}>
+ response_type: RANDOM
+ response_size: 314159
+ payload:{
+ body: 271828 bytes of zeros
+ }
+ }
+ ```
+ Client asserts:
+ * call was successful
+ * response payload type is either COMPRESSABLE or UNCOMPRESSABLE
+ * the behavior is consistent with the randomly chosen incoming payload type,
+ as described in their respective sections.
+
### client_streaming
This test verifies that client-only streaming succeeds.
@@ -184,6 +265,112 @@ Client asserts:
* clients are free to assert that the response payload body contents are zero
and comparing the entire response messages against golden responses
+### server_compressed_streaming
+
+This test verifies that server-only compressed streaming succeeds.
+
+Server features:
+* [StreamingOutputCall][]
+* [Compressable Payload][]
+* [Uncompressable Payload][]
+* [Random Payload][]
+
+
+Procedure:
+ 1. Client calls StreamingOutputCall with:
+
+ ```
+ {
+ response_compression: <one of {NONE, GZIP, DEFLATE}>
+ response_type:COMPRESSABLE
+ response_parameters:{
+ size: 31415
+ }
+ response_parameters:{
+ size: 9
+ }
+ response_parameters:{
+ size: 2653
+ }
+ response_parameters:{
+ size: 58979
+ }
+ }
+ ```
+
+ Client asserts:
+ * call was successful
+ * exactly four responses
+ * response payloads are COMPRESSABLE
+ * response compression is consistent with the requested one.
+ * if `response_compression == NONE`, the response MUST NOT have the
+ compressed message flag set.
+ * if `response_compression != NONE`, the response MUST have the compressed
+ message flag set.
+ * response payload bodies are sized (in order): 31415, 9, 2653, 58979
+ * clients are free to assert that the response payload body contents are
+ zero and comparing the entire response messages against golden responses
+
+
+ 2. Client calls StreamingOutputCall with:
+
+ ```
+ {
+ response_compression: <one of {NONE, GZIP, DEFLATE}>
+ response_type:UNCOMPRESSABLE
+ response_parameters:{
+ size: 31415
+ }
+ response_parameters:{
+ size: 9
+ }
+ response_parameters:{
+ size: 2653
+ }
+ response_parameters:{
+ size: 58979
+ }
+ }
+ ```
+
+ Client asserts:
+ * call was successful
+ * exactly four responses
+ * response payloads are UNCOMPRESSABLE
+ * response compressions are consistent with the requested one.
+ * the responses MUST NOT have the compressed message flag set.
+ * response payload bodies are sized (in order): 31415, 9, 2653, 58979
+ * clients are free to assert that the body of the responses are identical to
+ the golden uncompressable data at `test/cpp/interop/rnd.dat`.
+
+
+ 3. Client calls StreamingOutputCall with:
+
+ ```
+ {
+ response_compression: <one of {NONE, GZIP, DEFLATE}>
+ response_type:RANDOM
+ response_parameters:{
+ size: 31415
+ }
+ response_parameters:{
+ size: 9
+ }
+ response_parameters:{
+ size: 2653
+ }
+ response_parameters:{
+ size: 58979
+ }
+ }
+ ```
+
+ Client asserts:
+ * call was successful
+ * response payload type is either COMPRESSABLE or UNCOMPRESSABLE
+ * the behavior is consistent with the randomly chosen incoming payload type,
+ as described in their respective sections.
+
### ping_pong
This test verifies that full duplex bidi is supported.
@@ -825,6 +1012,21 @@ When the client requests COMPRESSABLE payload, the response includes a payload
of the size requested containing all zeros and the payload type is
COMPRESSABLE.
+### Uncompressable Payload
+[Uncompressable Payload]: #uncompressable-payload
+
+When the client requests UNCOMPRESSABLE payload, the response includes a payload
+of the size requested containing uncompressable data and the payload type is
+UNCOMPRESSABLE. A 512 kB dump from /dev/urandom is the current golden data,
+stored at `test/cpp/interop/rnd.dat`
+
+### Random Payload
+[Random Payload]: #random-payload
+
+When the client requests RANDOM payload, the response includes either a randomly
+chosen COMPRESSABLE or UNCOMPRESSABLE payload. The data and the payload type
+will be consistent with this choice.
+
### Echo Status
[Echo Status]: #echo-status
When the client sends a response_status in the request payload, the server closes