blob: 1c4a17fda84a668237f69b15b74bbf145d275abc [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 Tillere4222b42016-10-26 17:15:30 -070050#include "src/core/lib/slice/slice_string_helpers.h"
Yuchen Zeng955a3642016-06-17 13:48:03 -070051#include "src/core/lib/support/string.h"
52#include "test/core/end2end/cq_verifier.h"
53#include "test/core/util/port.h"
54#include "test/core/util/test_config.h"
55#include "test/core/util/test_tcp_server.h"
56
57#define HTTP1_RESP \
58 "HTTP/1.0 400 Bad Request\n" \
59 "Content-Type: text/html; charset=UTF-8\n" \
60 "Content-Length: 0\n" \
61 "Date: Tue, 07 Jun 2016 17:43:20 GMT\n\n"
62
63#define HTTP2_RESP(STATUS_CODE) \
64 "\x00\x00\x00\x04\x00\x00\x00\x00\x00" \
Yuchen Zengd9c6ac02016-06-22 11:11:46 -070065 "\x00\x00>\x01\x04\x00\x00\x00\x01" \
Yuchen Zeng955a3642016-06-17 13:48:03 -070066 "\x10\x0e" \
67 "content-length\x01" \
68 "0" \
69 "\x10\x0c" \
Yuchen Zengd9c6ac02016-06-22 11:11:46 -070070 "content-type\x10" \
71 "application/grpc" \
Yuchen Zeng955a3642016-06-17 13:48:03 -070072 "\x10\x07:status\x03" #STATUS_CODE
73
74#define UNPARSEABLE_RESP "Bad Request\n"
75
Yuchen Zeng955a3642016-06-17 13:48:03 -070076#define HTTP2_DETAIL_MSG(STATUS_CODE) \
77 "Received http2 header with status: " #STATUS_CODE
78
Yuchen Zeng753b45d2016-06-30 19:16:59 -070079#define UNPARSEABLE_DETAIL_MSG "Failed parsing HTTP/2"
Yuchen Zeng955a3642016-06-17 13:48:03 -070080
Yuchen Zeng9f340952016-07-11 15:15:40 -070081#define HTTP1_DETAIL_MSG "Trying to connect an http1.x server"
82
Yuchen Zengdf4455a2016-06-24 16:15:18 -070083/* TODO(zyc) Check the content of incomming data instead of using this length */
84#define EXPECTED_INCOMING_DATA_LENGTH (size_t)310
85
Yuchen Zeng955a3642016-06-17 13:48:03 -070086struct rpc_state {
87 char *target;
88 grpc_completion_queue *cq;
89 grpc_channel *channel;
90 grpc_call *call;
91 size_t incoming_data_length;
Craig Tillerd41a4a72016-10-26 16:16:06 -070092 grpc_slice_buffer temp_incoming_buffer;
93 grpc_slice_buffer outgoing_buffer;
Yuchen Zeng955a3642016-06-17 13:48:03 -070094 grpc_endpoint *tcp;
95 gpr_atm done_atm;
96 bool write_done;
97 const char *response_payload;
98 size_t response_payload_length;
99};
100
101static int server_port;
102static struct rpc_state state;
103static grpc_closure on_read;
104static grpc_closure on_write;
105
106static void *tag(intptr_t t) { return (void *)t; }
107
Yuchen Zengadb65a62016-06-20 15:56:43 -0700108static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
109 GPR_ASSERT(error == GRPC_ERROR_NONE);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700110
111 gpr_atm_rel_store(&state.done_atm, 1);
112}
113
114static void handle_write(grpc_exec_ctx *exec_ctx) {
Craig Tillere4222b42016-10-26 17:15:30 -0700115 grpc_slice slice = grpc_slice_from_copied_buffer(
116 state.response_payload, state.response_payload_length);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700117
Craig Tillerd41a4a72016-10-26 16:16:06 -0700118 grpc_slice_buffer_reset_and_unref(&state.outgoing_buffer);
119 grpc_slice_buffer_add(&state.outgoing_buffer, slice);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700120 grpc_endpoint_write(exec_ctx, state.tcp, &state.outgoing_buffer, &on_write);
121}
122
Yuchen Zengadb65a62016-06-20 15:56:43 -0700123static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
124 GPR_ASSERT(error == GRPC_ERROR_NONE);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700125 state.incoming_data_length += state.temp_incoming_buffer.length;
126
127 size_t i;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700128 for (i = 0; i < state.temp_incoming_buffer.count; i++) {
Craig Tiller0f310802016-10-26 16:25:56 -0700129 char *dump = grpc_dump_slice(state.temp_incoming_buffer.slices[i],
Craig Tillere4222b42016-10-26 17:15:30 -0700130 GPR_DUMP_HEX | GPR_DUMP_ASCII);
Yuchen Zengd9c6ac02016-06-22 11:11:46 -0700131 gpr_log(GPR_DEBUG, "Server received: %s", dump);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700132 gpr_free(dump);
133 }
134
Yuchen Zengc8e47ca2016-06-28 12:47:49 -0700135 gpr_log(GPR_DEBUG, "got %" PRIuPTR " bytes, expected %" PRIuPTR " bytes",
Yuchen Zengdf4455a2016-06-24 16:15:18 -0700136 state.incoming_data_length, EXPECTED_INCOMING_DATA_LENGTH);
137 if (state.incoming_data_length > EXPECTED_INCOMING_DATA_LENGTH) {
Yuchen Zeng955a3642016-06-17 13:48:03 -0700138 handle_write(exec_ctx);
139 } else {
140 grpc_endpoint_read(exec_ctx, state.tcp, &state.temp_incoming_buffer,
141 &on_read);
142 }
143}
144
145static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
146 grpc_pollset *accepting_pollset,
147 grpc_tcp_server_acceptor *acceptor) {
148 test_tcp_server *server = arg;
149 grpc_closure_init(&on_read, handle_read, NULL);
150 grpc_closure_init(&on_write, done_write, NULL);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700151 grpc_slice_buffer_init(&state.temp_incoming_buffer);
152 grpc_slice_buffer_init(&state.outgoing_buffer);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700153 state.tcp = tcp;
Yuchen Zengdf4455a2016-06-24 16:15:18 -0700154 state.incoming_data_length = 0;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700155 grpc_endpoint_add_to_pollset(exec_ctx, tcp, server->pollset);
156 grpc_endpoint_read(exec_ctx, tcp, &state.temp_incoming_buffer, &on_read);
157}
158
159static gpr_timespec n_sec_deadline(int seconds) {
160 return gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
161 gpr_time_from_seconds(seconds, GPR_TIMESPAN));
162}
163
164static void start_rpc(int target_port, grpc_status_code expected_status,
165 const char *expected_detail) {
166 grpc_op ops[6];
167 grpc_op *op;
168 grpc_metadata_array initial_metadata_recv;
169 grpc_metadata_array trailing_metadata_recv;
170 grpc_status_code status;
171 grpc_call_error error;
172 cq_verifier *cqv;
173 char *details = NULL;
174 size_t details_capacity = 0;
175
176 state.cq = grpc_completion_queue_create(NULL);
177 cqv = cq_verifier_create(state.cq);
178 gpr_join_host_port(&state.target, "127.0.0.1", target_port);
179 state.channel = grpc_insecure_channel_create(state.target, NULL, NULL);
180 state.call = grpc_channel_create_call(
181 state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq, "/Service/Method",
182 "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
183
184 grpc_metadata_array_init(&initial_metadata_recv);
185 grpc_metadata_array_init(&trailing_metadata_recv);
186
Yuchen Zengd9c6ac02016-06-22 11:11:46 -0700187 memset(ops, 0, sizeof(ops));
Yuchen Zeng955a3642016-06-17 13:48:03 -0700188 op = ops;
189 op->op = GRPC_OP_SEND_INITIAL_METADATA;
190 op->data.send_initial_metadata.count = 0;
191 op->flags = 0;
192 op->reserved = NULL;
193 op++;
194 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
195 op->flags = 0;
196 op->reserved = NULL;
197 op++;
198 op->op = GRPC_OP_RECV_INITIAL_METADATA;
199 op->data.recv_initial_metadata = &initial_metadata_recv;
200 op->flags = 0;
201 op->reserved = NULL;
202 op++;
203 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
204 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
205 op->data.recv_status_on_client.status = &status;
206 op->data.recv_status_on_client.status_details = &details;
207 op->data.recv_status_on_client.status_details_capacity = &details_capacity;
208 op->flags = 0;
209 op->reserved = NULL;
210 op++;
211 error =
212 grpc_call_start_batch(state.call, ops, (size_t)(op - ops), tag(1), NULL);
213
214 GPR_ASSERT(GRPC_CALL_OK == error);
215
Mark D. Roth7187ab92016-08-24 13:49:22 -0700216 CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700217 cq_verify(cqv);
218
219 gpr_log(GPR_DEBUG, "Rpc status: %d, details: %s", status, details);
220 GPR_ASSERT(status == expected_status);
Yuchen Zeng753b45d2016-06-30 19:16:59 -0700221 GPR_ASSERT(NULL != strstr(details, expected_detail));
Yuchen Zengd9c6ac02016-06-22 11:11:46 -0700222
223 grpc_metadata_array_destroy(&initial_metadata_recv);
224 grpc_metadata_array_destroy(&trailing_metadata_recv);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700225 gpr_free(details);
226 cq_verifier_destroy(cqv);
227}
228
229static void cleanup_rpc(void) {
230 grpc_event ev;
Craig Tillerd41a4a72016-10-26 16:16:06 -0700231 grpc_slice_buffer_destroy(&state.temp_incoming_buffer);
232 grpc_slice_buffer_destroy(&state.outgoing_buffer);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700233 grpc_call_destroy(state.call);
234 grpc_completion_queue_shutdown(state.cq);
235 do {
236 ev = grpc_completion_queue_next(state.cq, n_sec_deadline(1), NULL);
237 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
238 grpc_completion_queue_destroy(state.cq);
239 grpc_channel_destroy(state.channel);
240 gpr_free(state.target);
241}
242
243typedef struct {
244 test_tcp_server *server;
245 gpr_event *signal_when_done;
246} poll_args;
247
248static void actually_poll_server(void *arg) {
249 poll_args *pa = arg;
250 gpr_timespec deadline = n_sec_deadline(10);
251 while (true) {
252 bool done = gpr_atm_acq_load(&state.done_atm) != 0;
253 gpr_timespec time_left =
254 gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME));
Yuchen Zengadb65a62016-06-20 15:56:43 -0700255 gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRId64 ".%09d", done,
256 time_left.tv_sec, time_left.tv_nsec);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700257 if (done || gpr_time_cmp(time_left, gpr_time_0(GPR_TIMESPAN)) < 0) {
258 break;
259 }
260 test_tcp_server_poll(pa->server, 1);
261 }
262 gpr_event_set(pa->signal_when_done, (void *)1);
263 gpr_free(pa);
264}
265
266static void poll_server_until_read_done(test_tcp_server *server,
267 gpr_event *signal_when_done) {
268 gpr_atm_rel_store(&state.done_atm, 0);
269 state.write_done = 0;
270 gpr_thd_id id;
271 poll_args *pa = gpr_malloc(sizeof(*pa));
272 pa->server = server;
273 pa->signal_when_done = signal_when_done;
274 gpr_thd_new(&id, actually_poll_server, pa, NULL);
275}
276
277static void run_test(const char *response_payload,
278 size_t response_payload_length,
279 grpc_status_code expected_status,
280 const char *expected_detail) {
281 test_tcp_server test_server;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700282 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
283 gpr_event ev;
Yuchen Zeng955a3642016-06-17 13:48:03 -0700284
Yuchen Zengf7c7f332016-06-22 13:37:02 -0700285 grpc_init();
286 gpr_event_init(&ev);
287 server_port = grpc_pick_unused_port_or_die();
Yuchen Zeng955a3642016-06-17 13:48:03 -0700288 test_tcp_server_init(&test_server, on_connect, &test_server);
289 test_tcp_server_start(&test_server, server_port);
290 state.response_payload = response_payload;
291 state.response_payload_length = response_payload_length;
292
293 /* poll server until sending out the response */
294 poll_server_until_read_done(&test_server, &ev);
295 start_rpc(server_port, expected_status, expected_detail);
296 gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
297
298 /* clean up */
299 grpc_endpoint_shutdown(&exec_ctx, state.tcp);
300 grpc_endpoint_destroy(&exec_ctx, state.tcp);
301 grpc_exec_ctx_finish(&exec_ctx);
302 cleanup_rpc();
303 test_tcp_server_destroy(&test_server);
Yuchen Zengf7c7f332016-06-22 13:37:02 -0700304
305 grpc_shutdown();
Yuchen Zeng955a3642016-06-17 13:48:03 -0700306}
307
308int main(int argc, char **argv) {
309 grpc_test_init(argc, argv);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700310
311 /* status defined in hpack static table */
312 run_test(HTTP2_RESP(204), sizeof(HTTP2_RESP(204)) - 1, GRPC_STATUS_CANCELLED,
313 HTTP2_DETAIL_MSG(204));
314
315 run_test(HTTP2_RESP(206), sizeof(HTTP2_RESP(206)) - 1, GRPC_STATUS_CANCELLED,
316 HTTP2_DETAIL_MSG(206));
317
318 run_test(HTTP2_RESP(304), sizeof(HTTP2_RESP(304)) - 1, GRPC_STATUS_CANCELLED,
319 HTTP2_DETAIL_MSG(304));
320
321 run_test(HTTP2_RESP(400), sizeof(HTTP2_RESP(400)) - 1, GRPC_STATUS_CANCELLED,
322 HTTP2_DETAIL_MSG(400));
323
324 run_test(HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1, GRPC_STATUS_CANCELLED,
325 HTTP2_DETAIL_MSG(404));
326
327 run_test(HTTP2_RESP(500), sizeof(HTTP2_RESP(500)) - 1, GRPC_STATUS_CANCELLED,
328 HTTP2_DETAIL_MSG(500));
329
330 /* status not defined in hpack static table */
331 run_test(HTTP2_RESP(401), sizeof(HTTP2_RESP(401)) - 1, GRPC_STATUS_CANCELLED,
332 HTTP2_DETAIL_MSG(401));
333
334 run_test(HTTP2_RESP(403), sizeof(HTTP2_RESP(403)) - 1, GRPC_STATUS_CANCELLED,
335 HTTP2_DETAIL_MSG(403));
336
337 run_test(HTTP2_RESP(502), sizeof(HTTP2_RESP(502)) - 1, GRPC_STATUS_CANCELLED,
338 HTTP2_DETAIL_MSG(502));
339
340 /* unparseable response */
341 run_test(UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1,
342 GRPC_STATUS_UNAVAILABLE, UNPARSEABLE_DETAIL_MSG);
343
344 /* http1 response */
345 run_test(HTTP1_RESP, sizeof(HTTP1_RESP) - 1, GRPC_STATUS_UNAVAILABLE,
Yuchen Zeng9f340952016-07-11 15:15:40 -0700346 HTTP1_DETAIL_MSG);
Yuchen Zeng955a3642016-06-17 13:48:03 -0700347
Yuchen Zeng955a3642016-06-17 13:48:03 -0700348 return 0;
349}