mirror of https://github.com/grpc/grpc.git
commit
7567bd7892
127 changed files with 1624 additions and 611 deletions
@ -0,0 +1,44 @@ |
||||
# Copyright 2019 The gRPC Authors |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
py_binary( |
||||
name = "server", |
||||
srcs = ["server.py"], |
||||
deps = [ |
||||
"//src/python/grpcio/grpc:grpcio", |
||||
"//examples:py_helloworld", |
||||
], |
||||
srcs_version = "PY2AND3", |
||||
) |
||||
|
||||
py_binary( |
||||
name = "client", |
||||
srcs = ["client.py"], |
||||
deps = [ |
||||
"//src/python/grpcio/grpc:grpcio", |
||||
"//examples:py_helloworld", |
||||
], |
||||
srcs_version = "PY2AND3", |
||||
) |
||||
|
||||
py_test( |
||||
name = "test/compression_example_test", |
||||
srcs = ["test/compression_example_test.py"], |
||||
srcs_version = "PY2AND3", |
||||
data = [ |
||||
":client", |
||||
":server", |
||||
], |
||||
size = "small", |
||||
) |
@ -0,0 +1,58 @@ |
||||
## Compression with gRPC Python |
||||
|
||||
gRPC offers lossless compression options in order to decrease the number of bits |
||||
transferred over the wire. Three levels of compression are available: |
||||
|
||||
- `grpc.Compression.NoCompression` - No compression is applied to the payload. (default) |
||||
- `grpc.Compression.Deflate` - The "Deflate" algorithm is applied to the payload. |
||||
- `grpc.Compression.Gzip` - The Gzip algorithm is applied to the payload. |
||||
|
||||
The default option on both clients and servers is `grpc.Compression.NoCompression`. |
||||
|
||||
See [the gRPC Compression Spec](https://github.com/grpc/grpc/blob/master/doc/compression.md) |
||||
for more information. |
||||
|
||||
### Client Side Compression |
||||
|
||||
Compression may be set at two levels on the client side. |
||||
|
||||
#### At the channel level |
||||
|
||||
```python |
||||
with grpc.insecure_channel('foo.bar:1234', compression=grpc.Compression.Gzip) as channel: |
||||
use_channel(channel) |
||||
``` |
||||
|
||||
#### At the call level |
||||
|
||||
Setting the compression method at the call level will override any settings on |
||||
the channel level. |
||||
|
||||
```python |
||||
stub = helloworld_pb2_grpc.GreeterStub(channel) |
||||
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'), |
||||
compression=grpc.Compression.Deflate) |
||||
``` |
||||
|
||||
|
||||
### Server Side Compression |
||||
|
||||
Additionally, compression may be set at two levels on the server side. |
||||
|
||||
#### On the entire server |
||||
|
||||
```python |
||||
server = grpc.server(futures.ThreadPoolExecutor(), |
||||
compression=grpc.Compression.Gzip) |
||||
``` |
||||
|
||||
#### For an individual RPC |
||||
|
||||
```python |
||||
def SayHello(self, request, context): |
||||
context.set_response_compression(grpc.Compression.NoCompression) |
||||
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) |
||||
``` |
||||
|
||||
Setting the compression method for an individual RPC will override any setting |
||||
supplied at server creation time. |
@ -0,0 +1,76 @@ |
||||
# Copyright 2019 the gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
"""An example of compression on the client side with gRPC.""" |
||||
|
||||
from __future__ import absolute_import |
||||
from __future__ import division |
||||
from __future__ import print_function |
||||
|
||||
import argparse |
||||
import logging |
||||
import grpc |
||||
|
||||
from examples import helloworld_pb2 |
||||
from examples import helloworld_pb2_grpc |
||||
|
||||
_DESCRIPTION = 'A client capable of compression.' |
||||
_COMPRESSION_OPTIONS = { |
||||
"none": grpc.Compression.NoCompression, |
||||
"deflate": grpc.Compression.Deflate, |
||||
"gzip": grpc.Compression.Gzip, |
||||
} |
||||
|
||||
_LOGGER = logging.getLogger(__name__) |
||||
|
||||
|
||||
def run_client(channel_compression, call_compression, target): |
||||
with grpc.insecure_channel( |
||||
target, compression=channel_compression) as channel: |
||||
stub = helloworld_pb2_grpc.GreeterStub(channel) |
||||
response = stub.SayHello( |
||||
helloworld_pb2.HelloRequest(name='you'), |
||||
compression=call_compression, |
||||
wait_for_ready=True) |
||||
print("Response: {}".format(response)) |
||||
|
||||
|
||||
def main(): |
||||
parser = argparse.ArgumentParser(description=_DESCRIPTION) |
||||
parser.add_argument( |
||||
'--channel_compression', |
||||
default='none', |
||||
nargs='?', |
||||
choices=_COMPRESSION_OPTIONS.keys(), |
||||
help='The compression method to use for the channel.') |
||||
parser.add_argument( |
||||
'--call_compression', |
||||
default='none', |
||||
nargs='?', |
||||
choices=_COMPRESSION_OPTIONS.keys(), |
||||
help='The compression method to use for an individual call.') |
||||
parser.add_argument( |
||||
'--server', |
||||
default='localhost:50051', |
||||
type=str, |
||||
nargs='?', |
||||
help='The host-port pair at which to reach the server.') |
||||
args = parser.parse_args() |
||||
channel_compression = _COMPRESSION_OPTIONS[args.channel_compression] |
||||
call_compression = _COMPRESSION_OPTIONS[args.call_compression] |
||||
run_client(channel_compression, call_compression, args.server) |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
logging.basicConfig() |
||||
main() |
@ -0,0 +1,109 @@ |
||||
# Copyright 2019 the gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
"""An example of compression on the server side with gRPC.""" |
||||
|
||||
from __future__ import absolute_import |
||||
from __future__ import division |
||||
from __future__ import print_function |
||||
|
||||
from concurrent import futures |
||||
import argparse |
||||
import logging |
||||
import threading |
||||
import time |
||||
import grpc |
||||
|
||||
from examples import helloworld_pb2 |
||||
from examples import helloworld_pb2_grpc |
||||
|
||||
_DESCRIPTION = 'A server capable of compression.' |
||||
_COMPRESSION_OPTIONS = { |
||||
"none": grpc.Compression.NoCompression, |
||||
"deflate": grpc.Compression.Deflate, |
||||
"gzip": grpc.Compression.Gzip, |
||||
} |
||||
_LOGGER = logging.getLogger(__name__) |
||||
|
||||
_SERVER_HOST = 'localhost' |
||||
_ONE_DAY_IN_SECONDS = 60 * 60 * 24 |
||||
|
||||
|
||||
class Greeter(helloworld_pb2_grpc.GreeterServicer): |
||||
|
||||
def __init__(self, no_compress_every_n): |
||||
super(Greeter, self).__init__() |
||||
self._no_compress_every_n = 0 |
||||
self._request_counter = 0 |
||||
self._counter_lock = threading.RLock() |
||||
|
||||
def _should_suppress_compression(self): |
||||
suppress_compression = False |
||||
with self._counter_lock: |
||||
if self._no_compress_every_n and self._request_counter % self._no_compress_every_n == 0: |
||||
suppress_compression = True |
||||
self._request_counter += 1 |
||||
return suppress_compression |
||||
|
||||
def SayHello(self, request, context): |
||||
if self._should_suppress_compression(): |
||||
context.set_response_compression(grpc.Compression.NoCompression) |
||||
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) |
||||
|
||||
|
||||
def run_server(server_compression, no_compress_every_n, port): |
||||
server = grpc.server( |
||||
futures.ThreadPoolExecutor(), |
||||
compression=server_compression, |
||||
options=(('grpc.so_reuseport', 1),)) |
||||
helloworld_pb2_grpc.add_GreeterServicer_to_server( |
||||
Greeter(no_compress_every_n), server) |
||||
address = '{}:{}'.format(_SERVER_HOST, port) |
||||
server.add_insecure_port(address) |
||||
server.start() |
||||
print("Server listening at '{}'".format(address)) |
||||
try: |
||||
while True: |
||||
time.sleep(_ONE_DAY_IN_SECONDS) |
||||
except KeyboardInterrupt: |
||||
server.stop(None) |
||||
|
||||
|
||||
def main(): |
||||
parser = argparse.ArgumentParser(description=_DESCRIPTION) |
||||
parser.add_argument( |
||||
'--server_compression', |
||||
default='none', |
||||
nargs='?', |
||||
choices=_COMPRESSION_OPTIONS.keys(), |
||||
help='The default compression method for the server.') |
||||
parser.add_argument( |
||||
'--no_compress_every_n', |
||||
type=int, |
||||
default=0, |
||||
nargs='?', |
||||
help='If set, every nth reply will be uncompressed.') |
||||
parser.add_argument( |
||||
'--port', |
||||
type=int, |
||||
default=50051, |
||||
nargs='?', |
||||
help='The port on which the server will listen.') |
||||
args = parser.parse_args() |
||||
run_server(_COMPRESSION_OPTIONS[args.server_compression], |
||||
args.no_compress_every_n, args.port) |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
logging.basicConfig() |
||||
main() |
@ -0,0 +1,62 @@ |
||||
# Copyright 2019 the gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
"""Test for compression example.""" |
||||
|
||||
import contextlib |
||||
import os |
||||
import socket |
||||
import subprocess |
||||
import unittest |
||||
|
||||
_BINARY_DIR = os.path.realpath( |
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')) |
||||
_SERVER_PATH = os.path.join(_BINARY_DIR, 'server') |
||||
_CLIENT_PATH = os.path.join(_BINARY_DIR, 'client') |
||||
|
||||
|
||||
@contextlib.contextmanager |
||||
def _get_port(): |
||||
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) |
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) |
||||
if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) == 0: |
||||
raise RuntimeError("Failed to set SO_REUSEPORT.") |
||||
sock.bind(('', 0)) |
||||
try: |
||||
yield sock.getsockname()[1] |
||||
finally: |
||||
sock.close() |
||||
|
||||
|
||||
class CompressionExampleTest(unittest.TestCase): |
||||
|
||||
def test_compression_example(self): |
||||
with _get_port() as test_port: |
||||
server_process = subprocess.Popen((_SERVER_PATH, '--port', |
||||
str(test_port), |
||||
'--server_compression', 'gzip')) |
||||
try: |
||||
server_target = 'localhost:{}'.format(test_port) |
||||
client_process = subprocess.Popen( |
||||
(_CLIENT_PATH, '--server', server_target, |
||||
'--channel_compression', 'gzip')) |
||||
client_return_code = client_process.wait() |
||||
self.assertEqual(0, client_return_code) |
||||
self.assertIsNone(server_process.poll()) |
||||
finally: |
||||
server_process.kill() |
||||
server_process.wait() |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
unittest.main(verbosity=2) |
@ -1,7 +1,7 @@ |
||||
<!-- This file is generated --> |
||||
<Project> |
||||
<PropertyGroup> |
||||
<GrpcCsharpVersion>1.22.0-dev</GrpcCsharpVersion> |
||||
<GrpcCsharpVersion>1.23.0-dev</GrpcCsharpVersion> |
||||
<GoogleProtobufVersion>3.7.0</GoogleProtobufVersion> |
||||
</PropertyGroup> |
||||
</Project> |
||||
|
@ -0,0 +1,66 @@ |
||||
#!/bin/bash |
||||
# Copyright 2019 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
# Don't run this script standalone. Instead, run from the repository root: |
||||
# ./tools/run_tests/run_tests.py -l objc |
||||
|
||||
set -ev |
||||
|
||||
cd $(dirname $0) |
||||
|
||||
BINDIR=../../../bins/$CONFIG |
||||
|
||||
[ -f $BINDIR/interop_server ] || { |
||||
echo >&2 "Can't find the test server. Make sure run_tests.py is making" \ |
||||
"interop_server before calling this script." |
||||
exit 1 |
||||
} |
||||
|
||||
[ -z "$(ps aux |egrep 'port_server\.py.*-p\s32766')" ] && { |
||||
echo >&2 "Can't find the port server. Start port server with tools/run_tests/start_port_server.py." |
||||
exit 1 |
||||
} |
||||
|
||||
PLAIN_PORT=$(curl localhost:32766/get) |
||||
TLS_PORT=$(curl localhost:32766/get) |
||||
|
||||
$BINDIR/interop_server --port=$PLAIN_PORT --max_send_message_size=8388608 & |
||||
$BINDIR/interop_server --port=$TLS_PORT --max_send_message_size=8388608 --use_tls & |
||||
|
||||
trap 'kill -9 `jobs -p` ; echo "EXIT TIME: $(date)"' EXIT |
||||
|
||||
set -o pipefail |
||||
|
||||
XCODEBUILD_FILTER='(^CompileC |^Ld |^ *[^ ]*clang |^ *cd |^ *export |^Libtool |^ *[^ ]*libtool |^CpHeader |^ *builtin-copy )' |
||||
|
||||
if [ -z $PLATFORM ]; then |
||||
DESTINATION='name=iPhone 8' |
||||
elif [ $PLATFORM == ios ]; then |
||||
DESTINATION='name=iPhone 8' |
||||
elif [ $PLATFORM == macos ]; then |
||||
DESTINATION='platform=macOS' |
||||
fi |
||||
|
||||
xcodebuild \ |
||||
-workspace Tests.xcworkspace \ |
||||
-scheme $SCHEME \ |
||||
-destination "$DESTINATION" \ |
||||
HOST_PORT_LOCALSSL=localhost:$TLS_PORT \ |
||||
HOST_PORT_LOCAL=localhost:$PLAIN_PORT \ |
||||
HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \ |
||||
test \ |
||||
| egrep -v "$XCODEBUILD_FILTER" \ |
||||
| egrep -v '^$' \ |
||||
| egrep -v "(GPBDictionary|GPBArray)" - |
@ -0,0 +1,132 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2019 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include <string> |
||||
|
||||
#include <gtest/gtest.h> |
||||
|
||||
#include <grpc/support/string_util.h> |
||||
#include "src/core/lib/surface/server.h" |
||||
#include "test/core/bad_client/bad_client.h" |
||||
|
||||
#define HEADER_FRAME_ID_1 \ |
||||
"\x00\x00\xc9\x01\x05\x00\x00\x00\x01" /* headers: generated from \
|
||||
simple_request.headers in this \
|
||||
directory */ \
|
||||
"\x10\x05:path\x08/foo/bar" \
|
||||
"\x10\x07:scheme\x04http" \
|
||||
"\x10\x07:method\x04POST" \
|
||||
"\x10\x0a:authority\x09localhost" \
|
||||
"\x10\x0c" \
|
||||
"content-type\x10" \
|
||||
"application/grpc" \
|
||||
"\x10\x14grpc-accept-encoding\x15" \
|
||||
"deflate,identity,gzip" \
|
||||
"\x10\x02te\x08trailers" \
|
||||
"\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" |
||||
|
||||
#define HEADER_FRAME_ID_2 \ |
||||
"\x00\x00\xc9\x01\x05\x00\x00\x00\x02" /* headers: generated from \
|
||||
simple_request.headers in this \
|
||||
directory */ \
|
||||
"\x10\x05:path\x08/foo/bar" \
|
||||
"\x10\x07:scheme\x04http" \
|
||||
"\x10\x07:method\x04POST" \
|
||||
"\x10\x0a:authority\x09localhost" \
|
||||
"\x10\x0c" \
|
||||
"content-type\x10" \
|
||||
"application/grpc" \
|
||||
"\x10\x14grpc-accept-encoding\x15" \
|
||||
"deflate,identity,gzip" \
|
||||
"\x10\x02te\x08trailers" \
|
||||
"\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" |
||||
|
||||
#define HEADER_FRAME_ID_3 \ |
||||
"\x00\x00\xc9\x01\x05\x00\x00\x00\x03" /* headers: generated from \
|
||||
simple_request.headers in this \
|
||||
directory */ \
|
||||
"\x10\x05:path\x08/foo/bar" \
|
||||
"\x10\x07:scheme\x04http" \
|
||||
"\x10\x07:method\x04POST" \
|
||||
"\x10\x0a:authority\x09localhost" \
|
||||
"\x10\x0c" \
|
||||
"content-type\x10" \
|
||||
"application/grpc" \
|
||||
"\x10\x14grpc-accept-encoding\x15" \
|
||||
"deflate,identity,gzip" \
|
||||
"\x10\x02te\x08trailers" \
|
||||
"\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)" |
||||
|
||||
namespace { |
||||
|
||||
void verifier(grpc_server* server, grpc_completion_queue* cq, |
||||
void* registered_method) { |
||||
while (grpc_server_has_open_connections(server)) { |
||||
GPR_ASSERT(grpc_completion_queue_next( |
||||
cq, grpc_timeout_milliseconds_to_deadline(20), nullptr) |
||||
.type == GRPC_QUEUE_TIMEOUT); |
||||
} |
||||
} |
||||
|
||||
TEST(BadStreamingId, RegularHeader) { |
||||
grpc_bad_client_arg args[2]; |
||||
args[0] = connection_preface_arg; |
||||
args[1].client_validator = nullptr; |
||||
args[1].client_payload = HEADER_FRAME_ID_1; |
||||
args[1].client_payload_length = sizeof(HEADER_FRAME_ID_1) - 1; |
||||
grpc_run_bad_client_test(verifier, args, 2, GRPC_BAD_CLIENT_DISCONNECT); |
||||
} |
||||
|
||||
TEST(BadStreamingId, NonClientStreamId) { |
||||
grpc_bad_client_arg args[2]; |
||||
args[0] = connection_preface_arg; |
||||
// send a header frame with non-client stream id 2
|
||||
args[1].client_validator = nullptr; |
||||
args[1].client_payload = HEADER_FRAME_ID_2; |
||||
args[1].client_payload_length = sizeof(HEADER_FRAME_ID_2) - 1; |
||||
grpc_run_bad_client_test(verifier, args, 2, GRPC_BAD_CLIENT_DISCONNECT); |
||||
} |
||||
|
||||
TEST(BadStreamingId, ClosedStreamId) { |
||||
grpc_bad_client_arg args[4]; |
||||
args[0] = connection_preface_arg; |
||||
// send a header frame with stream id 1
|
||||
args[1].client_validator = nullptr; |
||||
args[1].client_payload = HEADER_FRAME_ID_1; |
||||
args[1].client_payload_length = sizeof(HEADER_FRAME_ID_1) - 1; |
||||
// send a header frame with stream id 3
|
||||
args[2].client_validator = nullptr; |
||||
args[2].client_payload = HEADER_FRAME_ID_3; |
||||
args[2].client_payload_length = sizeof(HEADER_FRAME_ID_3) - 1; |
||||
// send a header frame with closed stream id 1 again
|
||||
args[3].client_validator = nullptr; |
||||
args[3].client_payload = HEADER_FRAME_ID_1; |
||||
args[3].client_payload_length = sizeof(HEADER_FRAME_ID_1) - 1; |
||||
grpc_run_bad_client_test(verifier, args, 4, GRPC_BAD_CLIENT_DISCONNECT); |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) { |
||||
grpc_init(); |
||||
grpc::testing::TestEnvironment env(argc, argv); |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
int retval = RUN_ALL_TESTS(); |
||||
grpc_shutdown(); |
||||
return retval; |
||||
} |
@ -0,0 +1,112 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2019 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include <string> |
||||
|
||||
#include <gtest/gtest.h> |
||||
|
||||
#include <grpc/support/string_util.h> |
||||
#include "src/core/lib/surface/server.h" |
||||
#include "test/core/bad_client/bad_client.h" |
||||
|
||||
#define APPEND_BUFFER(string, to_append) \ |
||||
((string).append((to_append), sizeof(to_append) - 1)) |
||||
|
||||
namespace { |
||||
|
||||
void verifier(grpc_server* server, grpc_completion_queue* cq, |
||||
void* registered_method) { |
||||
while (grpc_server_has_open_connections(server)) { |
||||
GPR_ASSERT(grpc_completion_queue_next( |
||||
cq, grpc_timeout_milliseconds_to_deadline(20), nullptr) |
||||
.type == GRPC_QUEUE_TIMEOUT); |
||||
} |
||||
} |
||||
|
||||
void FrameVerifier(const std::string& attack_vector) { |
||||
grpc_bad_client_arg args[2]; |
||||
args[0] = connection_preface_arg; |
||||
args[1].client_validator = nullptr; |
||||
args[1].client_payload = attack_vector.c_str(); |
||||
args[1].client_payload_length = attack_vector.size(); |
||||
grpc_run_bad_client_test(verifier, args, 2, GRPC_BAD_CLIENT_DISCONNECT); |
||||
} |
||||
|
||||
TEST(OutOfBounds, MaxFrameSizeDataFrame) { |
||||
std::string out_of_bounds_data; |
||||
// Send a data frame larger than 2^14
|
||||
APPEND_BUFFER(out_of_bounds_data, "\x01\x00\x00\x00\x00\x00\x00\x00\x01"); |
||||
out_of_bounds_data.append(1 << 16, 'a'); |
||||
FrameVerifier(out_of_bounds_data); |
||||
} |
||||
|
||||
TEST(OutOfBounds, BadSizePriorityFrame) { |
||||
std::string bad_size_priority_frame; |
||||
// Priority Frame should be a length of 5 octets
|
||||
APPEND_BUFFER(bad_size_priority_frame, |
||||
"\x00\x00\x03\x02\x00\x00\x00\x00\x01" |
||||
"\x11\x11\x12"); |
||||
FrameVerifier(bad_size_priority_frame); |
||||
} |
||||
|
||||
TEST(OutOfBounds, BadSizeRstStream) { |
||||
std::string bad_size_rst_stream; |
||||
// Rst Stream Frame should have a length of 4 octets
|
||||
APPEND_BUFFER(bad_size_rst_stream, |
||||
"\x00\x00\x02\x03\x00\x00\x00\x00\x01" |
||||
"\x11\x11"); |
||||
FrameVerifier(bad_size_rst_stream); |
||||
} |
||||
|
||||
TEST(OutOfBounds, BadSizeSettings) { |
||||
std::string bad_size_settings; |
||||
// Settings Frame should have a length which is a multiple of 6 octets
|
||||
APPEND_BUFFER(bad_size_settings, |
||||
"\x00\x00\x05\x04\x00\x00\x00\x00\x00" |
||||
"\x11\x11\x11\x11\x11"); |
||||
FrameVerifier(bad_size_settings); |
||||
} |
||||
|
||||
TEST(OutOfBounds, BadSizePing) { |
||||
std::string bad_size_ping; |
||||
// Rst Stream Frame should have a length of 8 octets
|
||||
APPEND_BUFFER(bad_size_ping, |
||||
"\x00\x00\x05\x06\x00\x00\x00\x00\x00" |
||||
"\x11\x11\x11\x11\x11"); |
||||
FrameVerifier(bad_size_ping); |
||||
} |
||||
|
||||
TEST(OutOfBounds, WindowUpdate) { |
||||
std::string bad_size_window_update; |
||||
// Window Update Frame should have a length of 4 octets
|
||||
APPEND_BUFFER(bad_size_window_update, |
||||
"\x00\x00\x01\x08\x00\x00\x00\x00\x00" |
||||
"\x11"); |
||||
FrameVerifier(bad_size_window_update); |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) { |
||||
grpc_init(); |
||||
grpc::testing::TestEnvironment env(argc, argv); |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
int retval = RUN_ALL_TESTS(); |
||||
grpc_shutdown(); |
||||
return retval; |
||||
} |
@ -1 +1 @@ |
||||
Subproject commit ec44c6c1675c25b9827aacd08c02433cccde7780 |
||||
Subproject commit 2fe3bd994b3189899d93f1d5a881e725e046fdc2 |
@ -1,42 +0,0 @@ |
||||
cc_library( |
||||
name = "gtest", |
||||
srcs = [ |
||||
"googletest/src/gtest-all.cc", |
||||
], |
||||
hdrs = glob([ |
||||
"googletest/include/**/*.h", |
||||
"googletest/src/*.cc", |
||||
"googletest/src/*.h", |
||||
]), |
||||
includes = [ |
||||
"googletest", |
||||
"googletest/include", |
||||
], |
||||
linkstatic = 1, |
||||
visibility = [ |
||||
"//visibility:public", |
||||
], |
||||
) |
||||
|
||||
cc_library( |
||||
name = "gmock", |
||||
srcs = [ |
||||
"googlemock/src/gmock-all.cc" |
||||
], |
||||
hdrs = glob([ |
||||
"googlemock/include/**/*.h", |
||||
"googlemock/src/*.cc", |
||||
"googlemock/src/*.h" |
||||
]), |
||||
includes = [ |
||||
"googlemock", |
||||
"googlemock/include", |
||||
], |
||||
deps = [ |
||||
":gtest", |
||||
], |
||||
linkstatic = 1, |
||||
visibility = [ |
||||
"//visibility:public", |
||||
], |
||||
) |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue