blob: c37a292af970bb1ce0cdec4689a69d238187b23c [file] [log] [blame]
Yuchen Zeng955a3642016-06-17 13:48:03 -07001/*
2 *
3 * Copyright 2016, Google Inc.
4 * 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 */
murgatroid99085f9af2016-10-24 09:55:44 -070033
34/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when
35 using that endpoint. Because of various transitive includes in uv.h,
36 including windows.h on Windows, uv.h must be included before other system
37 headers. Therefore, sockaddr.h must always be included first */
murgatroid99c36f6ea2016-10-03 09:24:09 -070038#include "src/core/lib/iomgr/sockaddr.h"
39
Yuchen Zeng955a3642016-06-17 13:48:03 -070040#include <string.h>
41
42#include <grpc/grpc.h>
Craig Tillere4222b42016-10-26 17:15:30 -070043#include <grpc/slice.h>
Yuchen Zeng955a3642016-06-17 13:48:03 -070044#include <grpc/support/alloc.h>
45#include <grpc/support/host_port.h>
46#include <grpc/support/log.h>
Yuchen Zeng955a3642016-06-17 13:48:03 -070047#include <grpc/support/thd.h>
48
Yuchen Zeng955a3642016-06-17 13:48:03 -070049#include "src/core/lib/iomgr/sockaddr.h"
Craig Tiller10cd3562016-11-09 15:20:59 -080050#include "src/core/lib/slice/slice_internal.h"
Craig Tillere4222b42016-10-26 17:15:30 -070051#include "src/core/lib/slice/slice_string_helpers.h"
Yuchen Zeng955a3642016-06-17 13:48:03 -070052#include "src/core/lib/support/string.h"
53#include "test/core/end2end/cq_verifier.h"
54#include "test/core/util/port.h"
55#include "test/core/util/test_config.h"
56#include "test/core/util/test_tcp_server.h"
57
58#define HTTP1_RESP \
59 "HTTP/1.0 400 Bad Request\n" \
60 "Content-Type: text/html; charset=UTF-8\n" \
61 "Content-Length: 0\n" \
62 "Date: Tue, 07 Jun 2016 17:43:20 GMT\n\n"
63
64#define HTTP2_RESP(STATUS_CODE) \
65 "\x00\x00\x00\x04\x00\x00\x00\x00\x00" \
Yuchen Zengd9c6ac02016-06-22 11:11:46 -070066 "\x00\x00>\x01\x04\x00\x00\x00\x01" \
Yuchen Zeng955a3642016-06-17 13:48:03 -070067 "\x10\x0e" \
68 "content-length\x01" \
69 "0" \
70 "\x10\x0c" \
Yuchen Zengd9c6ac02016-06-22 11:11:46 -070071 "content-type\x10" \
72 "application/grpc" \
Yuchen Zeng955a3642016-06-17 13:48:03 -070073 "\x10\x07:status\x03" #STATUS_CODE
74
75#define UNPARSEABLE_RESP "Bad Request\n"
76
Yuchen Zeng955a3642016-06-17 13:48:03 -070077#define HTTP2_DETAIL_MSG(STATUS_CODE) \
78 "Received http2 header with status: " #STATUS_CODE
79
Yuchen Zeng753b45d2016-06-30 19:16:59 -070080#define UNPARSEABLE_DETAIL_MSG "Failed parsing HTTP/2"
Yuchen Zeng955a3642016-06-17 13:48:03 -070081
Yuchen Zeng9f340952016-07-11 15:15:40 -070082#define HTTP1_DETAIL_MSG "Trying to connect an http1.x server"
83
Yuchen Zengdf4455a2016-06-24 16:15:18 -070084/* TODO(zyc) Check the content of incomming data instead of using this length */
David Garcia Quintas191d52c2017-02-01 12:46:05 -080085/* The 'bad' server will start sending responses after reading this amount of
86 * data from the client. */
87#define SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD (size_t)200
Yuchen Zengdf4455a2016-06-24 16:15:18 -070088
Yuchen Zeng955a3642016-06-17 13:48:03 -070089struct rpc_state {
90 char *target;
91 grpc_completion_queue *cq;
92 grpc_channel *channel;
93 grpc_call *call;
94 size_t incoming_data_length;
Craig Tillerd41a4a72016-10-26 16:16:06 -070095 grpc_slice_buffer temp_incoming_buffer;
96 grpc_slice_buffer outgoing_buffer;
Yuchen Zeng955a3642016-06-17 13:48:03 -070097 grpc_endpoint *tcp;
98 gpr_atm done_atm;
99 bool write_done;
100 const char *response_payload;
101 size_t response_payload_length;
102};
103
104static int server_port;
105static struct rpc_state state;
106static grpc_closure on_read;
107static grpc_closure on_write;
108
109static void *tag(intptr_t t) { return (void *)t; }
110
Yuchen Zengadb65a62016-06-20 15:56:43 -0700111static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
112 GPR_ASSERT(error == GRPC_ERROR_NONE);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700113
114 gpr_atm_rel_store(&state.done_atm, 1);
115}
116
117static void handle_write(grpc_exec_ctx *exec_ctx) {
Craig Tillere4222b42016-10-26 17:15:30 -0700118 grpc_slice slice = grpc_slice_from_copied_buffer(
119 state.response_payload, state.response_payload_length);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700120
Craig Tillerd41a4a72016-10-26 16:16:06 -0700121 grpc_slice_buffer_reset_and_unref(&state.outgoing_buffer);
122 grpc_slice_buffer_add(&state.outgoing_buffer, slice);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700123 grpc_endpoint_write(exec_ctx, state.tcp, &state.outgoing_buffer, &on_write);
124}
125
Yuchen Zengadb65a62016-06-20 15:56:43 -0700126static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
127 GPR_ASSERT(error == GRPC_ERROR_NONE);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700128 state.incoming_data_length += state.temp_incoming_buffer.length;
129
130 size_t i;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700131 for (i = 0; i < state.temp_incoming_buffer.count; i++) {
Craig Tiller0f310802016-10-26 16:25:56 -0700132 char *dump = grpc_dump_slice(state.temp_incoming_buffer.slices[i],
Craig Tillere4222b42016-10-26 17:15:30 -0700133 GPR_DUMP_HEX | GPR_DUMP_ASCII);
Yuchen Zengd9c6ac02016-06-22 11:11:46 -0700134 gpr_log(GPR_DEBUG, "Server received: %s", dump);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700135 gpr_free(dump);
136 }
137
Yuchen Zengc8e47ca2016-06-28 12:47:49 -0700138 gpr_log(GPR_DEBUG, "got %" PRIuPTR " bytes, expected %" PRIuPTR " bytes",
David Garcia Quintas191d52c2017-02-01 12:46:05 -0800139 state.incoming_data_length,
140 SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD);
141 if (state.incoming_data_length >=
142 SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD) {
Yuchen Zeng955a3642016-06-17 13:48:03 -0700143 handle_write(exec_ctx);
144 } else {
145 grpc_endpoint_read(exec_ctx, state.tcp, &state.temp_incoming_buffer,
146 &on_read);
147 }
148}
149
150static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
151 grpc_pollset *accepting_pollset,
152 grpc_tcp_server_acceptor *acceptor) {
Mark D. Roth96ba68d2016-12-09 17:21:26 +0000153 gpr_free(acceptor);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700154 test_tcp_server *server = arg;
Craig Tiller91031da2016-12-28 15:44:25 -0800155 grpc_closure_init(&on_read, handle_read, NULL, grpc_schedule_on_exec_ctx);
156 grpc_closure_init(&on_write, done_write, NULL, grpc_schedule_on_exec_ctx);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700157 grpc_slice_buffer_init(&state.temp_incoming_buffer);
158 grpc_slice_buffer_init(&state.outgoing_buffer);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700159 state.tcp = tcp;
Yuchen Zengdf4455a2016-06-24 16:15:18 -0700160 state.incoming_data_length = 0;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700161 grpc_endpoint_add_to_pollset(exec_ctx, tcp, server->pollset);
162 grpc_endpoint_read(exec_ctx, tcp, &state.temp_incoming_buffer, &on_read);
163}
164
165static gpr_timespec n_sec_deadline(int seconds) {
166 return gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
167 gpr_time_from_seconds(seconds, GPR_TIMESPAN));
168}
169
170static void start_rpc(int target_port, grpc_status_code expected_status,
171 const char *expected_detail) {
172 grpc_op ops[6];
173 grpc_op *op;
174 grpc_metadata_array initial_metadata_recv;
175 grpc_metadata_array trailing_metadata_recv;
176 grpc_status_code status;
177 grpc_call_error error;
178 cq_verifier *cqv;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800179 grpc_slice details;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700180
181 state.cq = grpc_completion_queue_create(NULL);
182 cqv = cq_verifier_create(state.cq);
183 gpr_join_host_port(&state.target, "127.0.0.1", target_port);
184 state.channel = grpc_insecure_channel_create(state.target, NULL, NULL);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800185 grpc_slice host = grpc_slice_from_static_string("localhost");
Yuchen Zeng955a3642016-06-17 13:48:03 -0700186 state.call = grpc_channel_create_call(
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800187 state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq,
188 grpc_slice_from_static_string("/Service/Method"), &host,
189 gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700190
191 grpc_metadata_array_init(&initial_metadata_recv);
192 grpc_metadata_array_init(&trailing_metadata_recv);
193
Yuchen Zengd9c6ac02016-06-22 11:11:46 -0700194 memset(ops, 0, sizeof(ops));
Yuchen Zeng955a3642016-06-17 13:48:03 -0700195 op = ops;
196 op->op = GRPC_OP_SEND_INITIAL_METADATA;
197 op->data.send_initial_metadata.count = 0;
198 op->flags = 0;
199 op->reserved = NULL;
200 op++;
201 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
202 op->flags = 0;
203 op->reserved = NULL;
204 op++;
205 op->op = GRPC_OP_RECV_INITIAL_METADATA;
Mark D. Roth435f9f22017-01-25 12:53:54 -0800206 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700207 op->flags = 0;
208 op->reserved = NULL;
209 op++;
210 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
211 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
212 op->data.recv_status_on_client.status = &status;
213 op->data.recv_status_on_client.status_details = &details;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700214 op->flags = 0;
215 op->reserved = NULL;
216 op++;
217 error =
218 grpc_call_start_batch(state.call, ops, (size_t)(op - ops), tag(1), NULL);
219
220 GPR_ASSERT(GRPC_CALL_OK == error);
221
Mark D. Roth7187ab92016-08-24 13:49:22 -0700222 CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700223 cq_verify(cqv);
224
Yuchen Zeng955a3642016-06-17 13:48:03 -0700225 GPR_ASSERT(status == expected_status);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800226 GPR_ASSERT(-1 != grpc_slice_slice(details, grpc_slice_from_static_string(
227 expected_detail)));
Yuchen Zengd9c6ac02016-06-22 11:11:46 -0700228
229 grpc_metadata_array_destroy(&initial_metadata_recv);
230 grpc_metadata_array_destroy(&trailing_metadata_recv);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800231 grpc_slice_unref(details);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700232 cq_verifier_destroy(cqv);
233}
234
Craig Tiller10cd3562016-11-09 15:20:59 -0800235static void cleanup_rpc(grpc_exec_ctx *exec_ctx) {
Yuchen Zeng955a3642016-06-17 13:48:03 -0700236 grpc_event ev;
Craig Tillera59c16c2016-10-31 07:25:01 -0700237 grpc_slice_buffer_destroy_internal(exec_ctx, &state.temp_incoming_buffer);
238 grpc_slice_buffer_destroy_internal(exec_ctx, &state.outgoing_buffer);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700239 grpc_call_destroy(state.call);
240 grpc_completion_queue_shutdown(state.cq);
241 do {
242 ev = grpc_completion_queue_next(state.cq, n_sec_deadline(1), NULL);
243 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
244 grpc_completion_queue_destroy(state.cq);
245 grpc_channel_destroy(state.channel);
246 gpr_free(state.target);
247}
248
249typedef struct {
250 test_tcp_server *server;
251 gpr_event *signal_when_done;
252} poll_args;
253
254static void actually_poll_server(void *arg) {
255 poll_args *pa = arg;
256 gpr_timespec deadline = n_sec_deadline(10);
257 while (true) {
258 bool done = gpr_atm_acq_load(&state.done_atm) != 0;
259 gpr_timespec time_left =
260 gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME));
Yuchen Zengadb65a62016-06-20 15:56:43 -0700261 gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRId64 ".%09d", done,
262 time_left.tv_sec, time_left.tv_nsec);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700263 if (done || gpr_time_cmp(time_left, gpr_time_0(GPR_TIMESPAN)) < 0) {
264 break;
265 }
266 test_tcp_server_poll(pa->server, 1);
267 }
268 gpr_event_set(pa->signal_when_done, (void *)1);
269 gpr_free(pa);
270}
271
272static void poll_server_until_read_done(test_tcp_server *server,
273 gpr_event *signal_when_done) {
274 gpr_atm_rel_store(&state.done_atm, 0);
275 state.write_done = 0;
276 gpr_thd_id id;
277 poll_args *pa = gpr_malloc(sizeof(*pa));
278 pa->server = server;
279 pa->signal_when_done = signal_when_done;
280 gpr_thd_new(&id, actually_poll_server, pa, NULL);
281}
282
283static void run_test(const char *response_payload,
284 size_t response_payload_length,
285 grpc_status_code expected_status,
286 const char *expected_detail) {
287 test_tcp_server test_server;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700288 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
289 gpr_event ev;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700290
Yuchen Zengf7c7f332016-06-22 13:37:02 -0700291 grpc_init();
292 gpr_event_init(&ev);
293 server_port = grpc_pick_unused_port_or_die();
Yuchen Zeng955a3642016-06-17 13:48:03 -0700294 test_tcp_server_init(&test_server, on_connect, &test_server);
295 test_tcp_server_start(&test_server, server_port);
296 state.response_payload = response_payload;
297 state.response_payload_length = response_payload_length;
298
299 /* poll server until sending out the response */
300 poll_server_until_read_done(&test_server, &ev);
301 start_rpc(server_port, expected_status, expected_detail);
302 gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
303
304 /* clean up */
Craig Tillercda759d2017-01-27 11:37:37 -0800305 grpc_endpoint_shutdown(&exec_ctx, state.tcp,
ncteisen4b36a3d2017-03-13 19:08:06 -0700306 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
Yuchen Zeng955a3642016-06-17 13:48:03 -0700307 grpc_endpoint_destroy(&exec_ctx, state.tcp);
Craig Tiller10cd3562016-11-09 15:20:59 -0800308 cleanup_rpc(&exec_ctx);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700309 grpc_exec_ctx_finish(&exec_ctx);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700310 test_tcp_server_destroy(&test_server);
Yuchen Zengf7c7f332016-06-22 13:37:02 -0700311
312 grpc_shutdown();
Yuchen Zeng955a3642016-06-17 13:48:03 -0700313}
314
315int main(int argc, char **argv) {
316 grpc_test_init(argc, argv);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700317
318 /* status defined in hpack static table */
319 run_test(HTTP2_RESP(204), sizeof(HTTP2_RESP(204)) - 1, GRPC_STATUS_CANCELLED,
320 HTTP2_DETAIL_MSG(204));
321
322 run_test(HTTP2_RESP(206), sizeof(HTTP2_RESP(206)) - 1, GRPC_STATUS_CANCELLED,
323 HTTP2_DETAIL_MSG(206));
324
325 run_test(HTTP2_RESP(304), sizeof(HTTP2_RESP(304)) - 1, GRPC_STATUS_CANCELLED,
326 HTTP2_DETAIL_MSG(304));
327
328 run_test(HTTP2_RESP(400), sizeof(HTTP2_RESP(400)) - 1, GRPC_STATUS_CANCELLED,
329 HTTP2_DETAIL_MSG(400));
330
331 run_test(HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1, GRPC_STATUS_CANCELLED,
332 HTTP2_DETAIL_MSG(404));
333
334 run_test(HTTP2_RESP(500), sizeof(HTTP2_RESP(500)) - 1, GRPC_STATUS_CANCELLED,
335 HTTP2_DETAIL_MSG(500));
336
337 /* status not defined in hpack static table */
338 run_test(HTTP2_RESP(401), sizeof(HTTP2_RESP(401)) - 1, GRPC_STATUS_CANCELLED,
339 HTTP2_DETAIL_MSG(401));
340
341 run_test(HTTP2_RESP(403), sizeof(HTTP2_RESP(403)) - 1, GRPC_STATUS_CANCELLED,
342 HTTP2_DETAIL_MSG(403));
343
344 run_test(HTTP2_RESP(502), sizeof(HTTP2_RESP(502)) - 1, GRPC_STATUS_CANCELLED,
345 HTTP2_DETAIL_MSG(502));
346
347 /* unparseable response */
348 run_test(UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1,
349 GRPC_STATUS_UNAVAILABLE, UNPARSEABLE_DETAIL_MSG);
350
351 /* http1 response */
352 run_test(HTTP1_RESP, sizeof(HTTP1_RESP) - 1, GRPC_STATUS_UNAVAILABLE,
Yuchen Zeng9f340952016-07-11 15:15:40 -0700353 HTTP1_DETAIL_MSG);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700354
Yuchen Zeng955a3642016-06-17 13:48:03 -0700355 return 0;
356}