blob: b328f478fa085ec7f217e611a5e87fbb6efc0afa [file] [log] [blame]
yangg06170572015-01-12 13:12:45 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
yangg06170572015-01-12 13:12:45 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
yang-g9e2f90c2015-08-21 15:35:03 -070034#include <signal.h>
35#include <unistd.h>
36
David Garcia Quintasc8993192015-07-22 09:10:39 -070037#include <fstream>
yangg06170572015-01-12 13:12:45 -080038#include <memory>
39#include <sstream>
40#include <thread>
41
Nicolas "Pixel" Nobleba608202015-02-20 02:48:03 +010042#include <gflags/gflags.h>
Craig Tillerf40df232016-03-25 13:38:14 -070043#include <grpc++/security/server_credentials.h>
yangg06170572015-01-12 13:12:45 -080044#include <grpc++/server.h>
45#include <grpc++/server_builder.h>
46#include <grpc++/server_context.h>
Craig Tillerf40df232016-03-25 13:38:14 -070047#include <grpc/grpc.h>
48#include <grpc/support/log.h>
49#include <grpc/support/useful.h>
David Garcia Quintasc8993192015-07-22 09:10:39 -070050
David Garcia Quintas74686ce2016-06-09 15:33:33 -070051#include "src/core/lib/transport/byte_stream.h"
Craig Tiller1b4e3302015-12-17 16:35:00 -080052#include "src/proto/grpc/testing/empty.grpc.pb.h"
53#include "src/proto/grpc/testing/messages.grpc.pb.h"
Craig Tillerf40df232016-03-25 13:38:14 -070054#include "src/proto/grpc/testing/test.grpc.pb.h"
55#include "test/cpp/interop/server_helper.h"
56#include "test/cpp/util/test_config.h"
yangg06170572015-01-12 13:12:45 -080057
yang-g035cf092015-09-18 12:11:05 -070058DEFINE_bool(use_tls, false, "Whether to use tls.");
yangg06170572015-01-12 13:12:45 -080059DEFINE_int32(port, 0, "Server port.");
60
61using grpc::Server;
62using grpc::ServerBuilder;
63using grpc::ServerContext;
64using grpc::ServerCredentials;
yangg06170572015-01-12 13:12:45 -080065using grpc::ServerReader;
66using grpc::ServerReaderWriter;
67using grpc::ServerWriter;
68using grpc::SslServerCredentialsOptions;
David Garcia Quintas7c0d9142015-07-23 04:58:20 -070069using grpc::testing::InteropServerContextInspector;
yangg06170572015-01-12 13:12:45 -080070using grpc::testing::Payload;
71using grpc::testing::PayloadType;
72using grpc::testing::SimpleRequest;
73using grpc::testing::SimpleResponse;
74using grpc::testing::StreamingInputCallRequest;
75using grpc::testing::StreamingInputCallResponse;
76using grpc::testing::StreamingOutputCallRequest;
77using grpc::testing::StreamingOutputCallResponse;
78using grpc::testing::TestService;
79using grpc::Status;
80
Craig Tiller2f3e2ec2015-02-20 13:07:50 -080081static bool got_sigint = false;
82
yang-gc10348a2016-02-19 16:05:10 -080083const char kEchoInitialMetadataKey[] = "x-grpc-test-echo-initial";
84const char kEchoTrailingBinMetadataKey[] = "x-grpc-test-echo-trailing-bin";
Makarand Dharmapurikarbfc7ada2016-02-22 15:42:18 -080085const char kEchoUserAgentKey[] = "x-grpc-test-echo-useragent";
yang-gc10348a2016-02-19 16:05:10 -080086
87void MaybeEchoMetadata(ServerContext* context) {
88 const auto& client_metadata = context->client_metadata();
89 GPR_ASSERT(client_metadata.count(kEchoInitialMetadataKey) <= 1);
90 GPR_ASSERT(client_metadata.count(kEchoTrailingBinMetadataKey) <= 1);
91
92 auto iter = client_metadata.find(kEchoInitialMetadataKey);
93 if (iter != client_metadata.end()) {
94 context->AddInitialMetadata(kEchoInitialMetadataKey, iter->second.data());
95 }
96 iter = client_metadata.find(kEchoTrailingBinMetadataKey);
97 if (iter != client_metadata.end()) {
98 context->AddTrailingMetadata(
99 kEchoTrailingBinMetadataKey,
100 grpc::string(iter->second.begin(), iter->second.end()));
101 }
Makarand Dharmapurikarbfc7ada2016-02-22 15:42:18 -0800102 // Check if client sent a magic key in the header that makes us echo
103 // back the user-agent (for testing purpose)
104 iter = client_metadata.find(kEchoUserAgentKey);
105 if (iter != client_metadata.end()) {
106 iter = client_metadata.find("user-agent");
107 if (iter != client_metadata.end()) {
108 context->AddInitialMetadata(kEchoUserAgentKey, iter->second.data());
109 }
110 }
yang-gc10348a2016-02-19 16:05:10 -0800111}
112
David Garcia Quintas5756c8f2016-06-07 18:00:44 -0700113bool SetPayload(PayloadType response_type, int size, Payload* payload) {
yangg06170572015-01-12 13:12:45 -0800114 payload->set_type(response_type);
David Garcia Quintasc8993192015-07-22 09:10:39 -0700115 switch (response_type) {
116 case PayloadType::COMPRESSABLE: {
117 std::unique_ptr<char[]> body(new char[size]());
118 payload->set_body(body.get(), size);
119 } break;
David Garcia Quintasc8993192015-07-22 09:10:39 -0700120 default:
David Garcia Quintas74686ce2016-06-09 15:33:33 -0700121 return false;
David Garcia Quintas80f39952015-07-21 16:07:36 -0700122 }
yangg06170572015-01-12 13:12:45 -0800123 return true;
124}
125
David Garcia Quintas9c512bd2015-07-20 23:43:53 -0700126template <typename RequestType>
127void SetResponseCompression(ServerContext* context,
128 const RequestType& request) {
David Garcia Quintas5756c8f2016-06-07 18:00:44 -0700129 if (request.request_compressed_response()) {
130 // Any level would do, let's go for HIGH because we are overachievers.
131 context->set_compression_level(GRPC_COMPRESS_LEVEL_HIGH);
David Garcia Quintas9c512bd2015-07-20 23:43:53 -0700132 }
133}
134
David Garcia Quintas74686ce2016-06-09 15:33:33 -0700135template <typename RequestType>
136bool CheckExpectedCompression(const ServerContext& context,
137 const RequestType& request) {
138 const InteropServerContextInspector inspector(context);
139 const grpc_compression_algorithm received_compression =
140 inspector.GetCallCompressionAlgorithm();
141
142 if (request.expect_compressed_request()) {
143 if (received_compression == GRPC_COMPRESS_NONE) {
144 // Expected some compression, got NONE. This is an error.
145 gpr_log(GPR_ERROR,
146 "Failure: Expected compression but got uncompressed request "
147 "from client.");
148 return false;
149 }
150 if (request.payload_type() == PayloadType::COMPRESSABLE) {
151 if (!(inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS)) {
152 gpr_log(GPR_ERROR,
153 "Failure: Requested compression in a compressable request, but "
154 "compression bit in message flags not set.");
155 return false;
156 }
157 }
158 } else {
159 // Didn't expect compression -> make sure the request is uncompressed
160 if (inspector.GetMessageFlags() & GRPC_WRITE_INTERNAL_COMPRESS) {
161 gpr_log(GPR_ERROR,
162 "Failure: Didn't requested compression, but compression bit in "
163 "message flags set.");
164 return false;
165 }
166 }
167 return true;
168}
169
yangg06170572015-01-12 13:12:45 -0800170class TestServiceImpl : public TestService::Service {
171 public:
172 Status EmptyCall(ServerContext* context, const grpc::testing::Empty* request,
173 grpc::testing::Empty* response) {
Makarand Dharmapurikarbfc7ada2016-02-22 15:42:18 -0800174 MaybeEchoMetadata(context);
yangg06170572015-01-12 13:12:45 -0800175 return Status::OK;
176 }
177
178 Status UnaryCall(ServerContext* context, const SimpleRequest* request,
179 SimpleResponse* response) {
yang-gc10348a2016-02-19 16:05:10 -0800180 MaybeEchoMetadata(context);
David Garcia Quintas2e1bb1b2015-08-10 14:05:57 -0700181 SetResponseCompression(context, *request);
David Garcia Quintas74686ce2016-06-09 15:33:33 -0700182 if (!CheckExpectedCompression(*context, *request)) {
183 return Status(grpc::StatusCode::INVALID_ARGUMENT,
184 "Compressed request expectation not met.");
185 }
David Garcia Quintas864d1862015-08-13 15:26:00 -0700186 if (request->response_size() > 0) {
yangg06170572015-01-12 13:12:45 -0800187 if (!SetPayload(request->response_type(), request->response_size(),
188 response->mutable_payload())) {
David Garcia Quintas74686ce2016-06-09 15:33:33 -0700189 return Status(grpc::StatusCode::INVALID_ARGUMENT,
190 "Error creating payload.");
yangg06170572015-01-12 13:12:45 -0800191 }
192 }
Abhishek Kumare1c867d2015-08-05 11:04:45 -0700193
194 if (request->has_response_status()) {
David Garcia Quintas2e1bb1b2015-08-10 14:05:57 -0700195 return Status(
196 static_cast<grpc::StatusCode>(request->response_status().code()),
197 request->response_status().message());
Abhishek Kumare1c867d2015-08-05 11:04:45 -0700198 }
David Garcia Quintas80f39952015-07-21 16:07:36 -0700199
yangg06170572015-01-12 13:12:45 -0800200 return Status::OK;
201 }
202
203 Status StreamingOutputCall(
204 ServerContext* context, const StreamingOutputCallRequest* request,
205 ServerWriter<StreamingOutputCallResponse>* writer) {
David Garcia Quintas9c512bd2015-07-20 23:43:53 -0700206 SetResponseCompression(context, *request);
yangg06170572015-01-12 13:12:45 -0800207 StreamingOutputCallResponse response;
208 bool write_success = true;
yangg06170572015-01-12 13:12:45 -0800209 for (int i = 0; write_success && i < request->response_parameters_size();
210 i++) {
David Garcia Quintas04ecfa12015-08-25 14:19:48 -0700211 if (!SetPayload(request->response_type(),
212 request->response_parameters(i).size(),
213 response.mutable_payload())) {
David Garcia Quintas74686ce2016-06-09 15:33:33 -0700214 return Status(grpc::StatusCode::INVALID_ARGUMENT,
215 "Error creating payload.");
David Garcia Quintas04ecfa12015-08-25 14:19:48 -0700216 }
yangg06170572015-01-12 13:12:45 -0800217 write_success = writer->Write(response);
218 }
219 if (write_success) {
220 return Status::OK;
221 } else {
222 return Status(grpc::StatusCode::INTERNAL, "Error writing response.");
223 }
224 }
225
226 Status StreamingInputCall(ServerContext* context,
227 ServerReader<StreamingInputCallRequest>* reader,
228 StreamingInputCallResponse* response) {
229 StreamingInputCallRequest request;
230 int aggregated_payload_size = 0;
231 while (reader->Read(&request)) {
David Garcia Quintas74686ce2016-06-09 15:33:33 -0700232 if (!CheckExpectedCompression(*context, request)) {
233 return Status(grpc::StatusCode::INVALID_ARGUMENT,
234 "Compressed request expectation not met.");
235 }
yang-gf6befe82015-08-13 13:51:53 -0700236 if (request.has_payload()) {
yangg06170572015-01-12 13:12:45 -0800237 aggregated_payload_size += request.payload().body().size();
238 }
239 }
240 response->set_aggregated_payload_size(aggregated_payload_size);
241 return Status::OK;
242 }
243
244 Status FullDuplexCall(
245 ServerContext* context,
246 ServerReaderWriter<StreamingOutputCallResponse,
247 StreamingOutputCallRequest>* stream) {
yang-gc10348a2016-02-19 16:05:10 -0800248 MaybeEchoMetadata(context);
yangg06170572015-01-12 13:12:45 -0800249 StreamingOutputCallRequest request;
250 StreamingOutputCallResponse response;
251 bool write_success = true;
252 while (write_success && stream->Read(&request)) {
David Garcia Quintas9c512bd2015-07-20 23:43:53 -0700253 SetResponseCompression(context, request);
yang-g69563b92015-07-10 15:32:11 -0700254 if (request.response_parameters_size() != 0) {
255 response.mutable_payload()->set_type(request.payload().type());
256 response.mutable_payload()->set_body(
257 grpc::string(request.response_parameters(0).size(), '\0'));
258 write_success = stream->Write(response);
yangg06170572015-01-12 13:12:45 -0800259 }
yangg06170572015-01-12 13:12:45 -0800260 }
261 if (write_success) {
262 return Status::OK;
263 } else {
264 return Status(grpc::StatusCode::INTERNAL, "Error writing response.");
265 }
266 }
267
268 Status HalfDuplexCall(
269 ServerContext* context,
270 ServerReaderWriter<StreamingOutputCallResponse,
271 StreamingOutputCallRequest>* stream) {
272 std::vector<StreamingOutputCallRequest> requests;
273 StreamingOutputCallRequest request;
274 while (stream->Read(&request)) {
275 requests.push_back(request);
276 }
277
278 StreamingOutputCallResponse response;
279 bool write_success = true;
280 for (unsigned int i = 0; write_success && i < requests.size(); i++) {
281 response.mutable_payload()->set_type(requests[i].payload().type());
282 if (requests[i].response_parameters_size() == 0) {
283 return Status(grpc::StatusCode::INTERNAL,
284 "Request does not have response parameters.");
285 }
286 response.mutable_payload()->set_body(
287 grpc::string(requests[i].response_parameters(0).size(), '\0'));
288 write_success = stream->Write(response);
289 }
290 if (write_success) {
291 return Status::OK;
292 } else {
293 return Status(grpc::StatusCode::INTERNAL, "Error writing response.");
294 }
295 }
296};
297
298void RunServer() {
299 std::ostringstream server_address;
Yang Gaodab70952015-01-23 16:06:36 -0800300 server_address << "0.0.0.0:" << FLAGS_port;
yangg06170572015-01-12 13:12:45 -0800301 TestServiceImpl service;
302
303 SimpleRequest request;
304 SimpleResponse response;
305
306 ServerBuilder builder;
Craig Tillerf8ac5d82015-02-09 16:24:20 -0800307 builder.RegisterService(&service);
Yang Gaoa4002072015-04-09 23:25:21 -0700308 std::shared_ptr<ServerCredentials> creds =
309 grpc::testing::CreateInteropServerCredentials();
Nicolas Noblecfd60732015-03-18 16:27:43 -0700310 builder.AddListeningPort(server_address.str(), creds);
yangg06170572015-01-12 13:12:45 -0800311 std::unique_ptr<Server> server(builder.BuildAndStart());
312 gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str());
Craig Tiller2f3e2ec2015-02-20 13:07:50 -0800313 while (!got_sigint) {
Craig Tillercf133f42015-02-26 14:05:56 -0800314 sleep(5);
yangg06170572015-01-12 13:12:45 -0800315 }
316}
317
Craig Tiller2f3e2ec2015-02-20 13:07:50 -0800318static void sigint_handler(int x) { got_sigint = true; }
319
yangg06170572015-01-12 13:12:45 -0800320int main(int argc, char** argv) {
Yang Gao103837e2015-04-15 15:23:54 -0700321 grpc::testing::InitTest(&argc, &argv, true);
Craig Tiller2f3e2ec2015-02-20 13:07:50 -0800322 signal(SIGINT, sigint_handler);
yangg06170572015-01-12 13:12:45 -0800323
324 GPR_ASSERT(FLAGS_port != 0);
325 RunServer();
326
yangg06170572015-01-12 13:12:45 -0800327 return 0;
Craig Tiller190d3602015-02-18 09:23:38 -0800328}