1 /*
2  *
3  * Copyright 2016 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #include <string.h>
20 
21 #include <grpc/grpc.h>
22 #include <grpc/slice.h>
23 #include <grpc/support/alloc.h>
24 #include <grpc/support/log.h>
25 
26 #include "src/core/lib/channel/channel_args.h"
27 #include "src/core/lib/gpr/string.h"
28 #include "src/core/lib/gprpp/host_port.h"
29 #include "src/core/lib/gprpp/memory.h"
30 #include "src/core/lib/gprpp/thd.h"
31 #include "src/core/lib/iomgr/sockaddr.h"
32 #include "src/core/lib/slice/slice_internal.h"
33 #include "src/core/lib/slice/slice_string_helpers.h"
34 #include "test/core/end2end/cq_verifier.h"
35 #include "test/core/util/port.h"
36 #include "test/core/util/test_config.h"
37 #include "test/core/util/test_tcp_server.h"
38 
39 #define HTTP1_RESP_400                       \
40   "HTTP/1.0 400 Bad Request\n"               \
41   "Content-Type: text/html; charset=UTF-8\n" \
42   "Content-Length: 0\n"                      \
43   "Date: Tue, 07 Jun 2016 17:43:20 GMT\n\n"
44 
45 #define HTTP2_SETTINGS_FRAME "\x00\x00\x00\x04\x00\x00\x00\x00\x00"
46 
47 #define HTTP2_RESP(STATUS_CODE)       \
48   "\x00\x00>\x01\x04\x00\x00\x00\x01" \
49   "\x10\x0e"                          \
50   "content-length\x01"                \
51   "0"                                 \
52   "\x10\x0c"                          \
53   "content-type\x10"                  \
54   "application/grpc"                  \
55   "\x10\x07:status\x03" #STATUS_CODE
56 
57 #define UNPARSEABLE_RESP "Bad Request\n"
58 
59 #define HTTP2_DETAIL_MSG(STATUS_CODE) \
60   "Received http2 header with status: " #STATUS_CODE
61 
62 /* TODO(zyc) Check the content of incoming data instead of using this length */
63 /* The 'bad' server will start sending responses after reading this amount of
64  * data from the client. */
65 #define SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD (size_t)200
66 
67 struct rpc_state {
68   std::string target;
69   grpc_completion_queue* cq;
70   grpc_channel* channel;
71   grpc_call* call;
72   size_t incoming_data_length;
73   grpc_slice_buffer temp_incoming_buffer;
74   grpc_slice_buffer outgoing_buffer;
75   grpc_endpoint* tcp;
76   gpr_atm done_atm;
77   bool http2_response;
78   bool send_settings;
79   const char* response_payload;
80   size_t response_payload_length;
81   bool connection_attempt_made;
82 };
83 
84 static int server_port;
85 static struct rpc_state state;
86 static grpc_closure on_read;
87 static grpc_closure on_writing_settings_frame;
88 static grpc_closure on_write;
89 
tag(intptr_t t)90 static void* tag(intptr_t t) { return reinterpret_cast<void*>(t); }
91 
done_write(void *,grpc_error_handle error)92 static void done_write(void* /*arg*/, grpc_error_handle error) {
93   GPR_ASSERT(error == GRPC_ERROR_NONE);
94   gpr_atm_rel_store(&state.done_atm, 1);
95 }
96 
done_writing_settings_frame(void *,grpc_error_handle error)97 static void done_writing_settings_frame(void* /* arg */,
98                                         grpc_error_handle error) {
99   GPR_ASSERT(error == GRPC_ERROR_NONE);
100   grpc_endpoint_read(state.tcp, &state.temp_incoming_buffer, &on_read,
101                      /*urgent=*/false);
102 }
103 
handle_write()104 static void handle_write() {
105   grpc_slice slice = grpc_slice_from_copied_buffer(
106       state.response_payload, state.response_payload_length);
107 
108   grpc_slice_buffer_reset_and_unref(&state.outgoing_buffer);
109   grpc_slice_buffer_add(&state.outgoing_buffer, slice);
110   grpc_endpoint_write(state.tcp, &state.outgoing_buffer, &on_write, nullptr);
111 }
112 
handle_read(void *,grpc_error_handle error)113 static void handle_read(void* /*arg*/, grpc_error_handle error) {
114   if (error != GRPC_ERROR_NONE) {
115     gpr_log(GPR_ERROR, "handle_read error: %s",
116             grpc_error_std_string(error).c_str());
117     return;
118   }
119   state.incoming_data_length += state.temp_incoming_buffer.length;
120 
121   size_t i;
122   for (i = 0; i < state.temp_incoming_buffer.count; i++) {
123     char* dump = grpc_dump_slice(state.temp_incoming_buffer.slices[i],
124                                  GPR_DUMP_HEX | GPR_DUMP_ASCII);
125     gpr_log(GPR_DEBUG, "Server received: %s", dump);
126     gpr_free(dump);
127   }
128 
129   gpr_log(GPR_DEBUG,
130           "got %" PRIuPTR " bytes, expected %" PRIuPTR
131           " bytes or a non-HTTP2 response to be sent",
132           state.incoming_data_length,
133           SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD);
134   if (state.incoming_data_length >=
135           SERVER_INCOMING_DATA_LENGTH_LOWER_THRESHOLD ||
136       !state.http2_response) {
137     handle_write();
138   } else {
139     grpc_endpoint_read(state.tcp, &state.temp_incoming_buffer, &on_read,
140                        /*urgent=*/false);
141   }
142 }
143 
on_connect(void * arg,grpc_endpoint * tcp,grpc_pollset *,grpc_tcp_server_acceptor * acceptor)144 static void on_connect(void* arg, grpc_endpoint* tcp,
145                        grpc_pollset* /*accepting_pollset*/,
146                        grpc_tcp_server_acceptor* acceptor) {
147   gpr_free(acceptor);
148   test_tcp_server* server = static_cast<test_tcp_server*>(arg);
149   GRPC_CLOSURE_INIT(&on_read, handle_read, nullptr, grpc_schedule_on_exec_ctx);
150   GRPC_CLOSURE_INIT(&on_writing_settings_frame, done_writing_settings_frame,
151                     nullptr, grpc_schedule_on_exec_ctx);
152   GRPC_CLOSURE_INIT(&on_write, done_write, nullptr, grpc_schedule_on_exec_ctx);
153   grpc_slice_buffer_init(&state.temp_incoming_buffer);
154   grpc_slice_buffer_init(&state.outgoing_buffer);
155   state.connection_attempt_made = true;
156   state.tcp = tcp;
157   state.incoming_data_length = 0;
158   grpc_endpoint_add_to_pollset(tcp, server->pollset[0]);
159   if (state.send_settings) {
160     // Send settings frame from server
161     grpc_slice slice = grpc_slice_from_static_buffer(
162         HTTP2_SETTINGS_FRAME, sizeof(HTTP2_SETTINGS_FRAME) - 1);
163     grpc_slice_buffer_add(&state.outgoing_buffer, slice);
164     grpc_endpoint_write(state.tcp, &state.outgoing_buffer,
165                         &on_writing_settings_frame, nullptr);
166   } else {
167     grpc_endpoint_read(state.tcp, &state.temp_incoming_buffer, &on_read,
168                        /*urgent=*/false);
169   }
170 }
171 
n_sec_deadline(int seconds)172 static gpr_timespec n_sec_deadline(int seconds) {
173   return gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
174                       gpr_time_from_seconds(seconds, GPR_TIMESPAN));
175 }
176 
start_rpc(int target_port,grpc_status_code expected_status,const char * expected_detail)177 static void start_rpc(int target_port, grpc_status_code expected_status,
178                       const char* expected_detail) {
179   grpc_op ops[6];
180   grpc_op* op;
181   grpc_metadata_array initial_metadata_recv;
182   grpc_metadata_array trailing_metadata_recv;
183   grpc_status_code status;
184   grpc_call_error error;
185   cq_verifier* cqv;
186   grpc_slice details;
187 
188   state.cq = grpc_completion_queue_create_for_next(nullptr);
189   cqv = cq_verifier_create(state.cq);
190   state.target = grpc_core::JoinHostPort("127.0.0.1", target_port);
191 
192   state.channel =
193       grpc_insecure_channel_create(state.target.c_str(), nullptr, nullptr);
194   grpc_slice host = grpc_slice_from_static_string("localhost");
195   // The default connect deadline is 20 seconds, so reduce the RPC deadline to 1
196   // second. This helps us verify - a) If the server responded with a non-HTTP2
197   // response, the connect fails immediately resulting in
198   // GRPC_STATUS_UNAVAILABLE instead of GRPC_STATUS_DEADLINE_EXCEEDED. b) If the
199   // server does not send a HTTP2 SETTINGs frame, the RPC fails with a
200   // DEADLINE_EXCEEDED.
201   state.call = grpc_channel_create_call(
202       state.channel, nullptr, GRPC_PROPAGATE_DEFAULTS, state.cq,
203       grpc_slice_from_static_string("/Service/Method"), &host,
204       n_sec_deadline(5), nullptr);
205 
206   grpc_metadata_array_init(&initial_metadata_recv);
207   grpc_metadata_array_init(&trailing_metadata_recv);
208 
209   memset(ops, 0, sizeof(ops));
210   op = ops;
211   op->op = GRPC_OP_SEND_INITIAL_METADATA;
212   op->data.send_initial_metadata.count = 0;
213   op->flags = 0;
214   op->reserved = nullptr;
215   op++;
216   op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
217   op->flags = 0;
218   op->reserved = nullptr;
219   op++;
220   op->op = GRPC_OP_RECV_INITIAL_METADATA;
221   op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
222   op->flags = 0;
223   op->reserved = nullptr;
224   op++;
225   op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
226   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
227   op->data.recv_status_on_client.status = &status;
228   op->data.recv_status_on_client.status_details = &details;
229   op->flags = 0;
230   op->reserved = nullptr;
231   op++;
232   error = grpc_call_start_batch(state.call, ops, static_cast<size_t>(op - ops),
233                                 tag(1), nullptr);
234 
235   GPR_ASSERT(GRPC_CALL_OK == error);
236 
237   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
238   cq_verify(cqv);
239 
240   GPR_ASSERT(status == expected_status);
241   if (expected_detail != nullptr) {
242     GPR_ASSERT(-1 != grpc_slice_slice(details, grpc_slice_from_static_string(
243                                                    expected_detail)));
244   }
245 
246   grpc_metadata_array_destroy(&initial_metadata_recv);
247   grpc_metadata_array_destroy(&trailing_metadata_recv);
248   grpc_slice_unref(details);
249   cq_verifier_destroy(cqv);
250 }
251 
cleanup_rpc()252 static void cleanup_rpc() {
253   grpc_event ev;
254   grpc_slice_buffer_destroy_internal(&state.temp_incoming_buffer);
255   grpc_slice_buffer_destroy_internal(&state.outgoing_buffer);
256   grpc_call_unref(state.call);
257   grpc_completion_queue_shutdown(state.cq);
258   do {
259     ev = grpc_completion_queue_next(state.cq, n_sec_deadline(1), nullptr);
260   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
261   grpc_completion_queue_destroy(state.cq);
262   grpc_channel_destroy(state.channel);
263   state.target.clear();
264 }
265 
266 typedef struct {
267   test_tcp_server* server;
268   gpr_event* signal_when_done;
269 } poll_args;
270 
actually_poll_server(void * arg)271 static void actually_poll_server(void* arg) {
272   poll_args* pa = static_cast<poll_args*>(arg);
273   gpr_timespec deadline = n_sec_deadline(5);
274   while (true) {
275     bool done = gpr_atm_acq_load(&state.done_atm) != 0;
276     gpr_timespec time_left =
277         gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME));
278     gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRId64 ".%09d", done,
279             time_left.tv_sec, time_left.tv_nsec);
280     if (done || gpr_time_cmp(time_left, gpr_time_0(GPR_TIMESPAN)) < 0) {
281       break;
282     }
283     test_tcp_server_poll(pa->server, 1000);
284   }
285   gpr_event_set(pa->signal_when_done, reinterpret_cast<void*>(1));
286   gpr_free(pa);
287 }
288 
poll_server_until_read_done(test_tcp_server * server,gpr_event * signal_when_done)289 static grpc_core::Thread* poll_server_until_read_done(
290     test_tcp_server* server, gpr_event* signal_when_done) {
291   gpr_atm_rel_store(&state.done_atm, 0);
292   state.connection_attempt_made = false;
293   poll_args* pa = static_cast<poll_args*>(gpr_malloc(sizeof(*pa)));
294   pa->server = server;
295   pa->signal_when_done = signal_when_done;
296   auto* th =
297       new grpc_core::Thread("grpc_poll_server", actually_poll_server, pa);
298   th->Start();
299   return th;
300 }
301 
run_test(bool http2_response,bool send_settings,const char * response_payload,size_t response_payload_length,grpc_status_code expected_status,const char * expected_detail)302 static void run_test(bool http2_response, bool send_settings,
303                      const char* response_payload,
304                      size_t response_payload_length,
305                      grpc_status_code expected_status,
306                      const char* expected_detail) {
307   test_tcp_server test_server;
308   grpc_core::ExecCtx exec_ctx;
309   gpr_event ev;
310 
311   grpc_init();
312   gpr_event_init(&ev);
313   server_port = grpc_pick_unused_port_or_die();
314   test_tcp_server_init(&test_server, on_connect, &test_server);
315   test_tcp_server_start(&test_server, server_port);
316   state.http2_response = http2_response;
317   state.send_settings = send_settings;
318   state.response_payload = response_payload;
319   state.response_payload_length = response_payload_length;
320 
321   /* poll server until sending out the response */
322   std::unique_ptr<grpc_core::Thread> thdptr(
323       poll_server_until_read_done(&test_server, &ev));
324   start_rpc(server_port, expected_status, expected_detail);
325   gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
326   thdptr->Join();
327   /* Proof that the server accepted the TCP connection. */
328   GPR_ASSERT(state.connection_attempt_made == true);
329   /* clean up */
330   grpc_endpoint_shutdown(state.tcp,
331                          GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
332   grpc_endpoint_destroy(state.tcp);
333   cleanup_rpc();
334   grpc_core::ExecCtx::Get()->Flush();
335   test_tcp_server_destroy(&test_server);
336 
337   grpc_shutdown();
338 }
339 
main(int argc,char ** argv)340 int main(int argc, char** argv) {
341   grpc::testing::TestEnvironment env(argc, argv);
342   grpc_init();
343 
344   /* status defined in hpack static table */
345   run_test(true, true, HTTP2_RESP(204), sizeof(HTTP2_RESP(204)) - 1,
346            GRPC_STATUS_UNKNOWN, HTTP2_DETAIL_MSG(204));
347   run_test(true, true, HTTP2_RESP(206), sizeof(HTTP2_RESP(206)) - 1,
348            GRPC_STATUS_UNKNOWN, HTTP2_DETAIL_MSG(206));
349   run_test(true, true, HTTP2_RESP(304), sizeof(HTTP2_RESP(304)) - 1,
350            GRPC_STATUS_UNKNOWN, HTTP2_DETAIL_MSG(304));
351   run_test(true, true, HTTP2_RESP(400), sizeof(HTTP2_RESP(400)) - 1,
352            GRPC_STATUS_INTERNAL, HTTP2_DETAIL_MSG(400));
353   run_test(true, true, HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1,
354            GRPC_STATUS_UNIMPLEMENTED, HTTP2_DETAIL_MSG(404));
355   run_test(true, true, HTTP2_RESP(500), sizeof(HTTP2_RESP(500)) - 1,
356            GRPC_STATUS_UNKNOWN, HTTP2_DETAIL_MSG(500));
357 
358   /* status not defined in hpack static table */
359   run_test(true, true, HTTP2_RESP(401), sizeof(HTTP2_RESP(401)) - 1,
360            GRPC_STATUS_UNAUTHENTICATED, HTTP2_DETAIL_MSG(401));
361   run_test(true, true, HTTP2_RESP(403), sizeof(HTTP2_RESP(403)) - 1,
362            GRPC_STATUS_PERMISSION_DENIED, HTTP2_DETAIL_MSG(403));
363   run_test(true, true, HTTP2_RESP(429), sizeof(HTTP2_RESP(429)) - 1,
364            GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(429));
365   run_test(true, true, HTTP2_RESP(499), sizeof(HTTP2_RESP(499)) - 1,
366            GRPC_STATUS_UNKNOWN, HTTP2_DETAIL_MSG(499));
367   run_test(true, true, HTTP2_RESP(502), sizeof(HTTP2_RESP(502)) - 1,
368            GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(502));
369   run_test(true, true, HTTP2_RESP(503), sizeof(HTTP2_RESP(503)) - 1,
370            GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(503));
371   run_test(true, true, HTTP2_RESP(504), sizeof(HTTP2_RESP(504)) - 1,
372            GRPC_STATUS_UNAVAILABLE, HTTP2_DETAIL_MSG(504));
373   /* unparseable response. RPC should fail immediately due to a connect failure.
374    */
375   run_test(false, false, UNPARSEABLE_RESP, sizeof(UNPARSEABLE_RESP) - 1,
376            GRPC_STATUS_UNAVAILABLE, nullptr);
377 
378   /* http1 response. RPC should fail immediately due to a connect failure. */
379   run_test(false, false, HTTP1_RESP_400, sizeof(HTTP1_RESP_400) - 1,
380            GRPC_STATUS_UNAVAILABLE, nullptr);
381 
382   /* http2 response without sending a SETTINGs frame. RPC should fail with
383    * DEADLINE_EXCEEDED since the RPC deadline is lower than the connection
384    * attempt deadline. */
385   run_test(true, false, HTTP2_RESP(404), sizeof(HTTP2_RESP(404)) - 1,
386            GRPC_STATUS_DEADLINE_EXCEEDED, nullptr);
387   grpc_shutdown();
388   return 0;
389 }
390