Send RPC deadline to server in cronet header

pull/19820/head
Prashant Jaikumar 5 years ago
parent e20c2e85d8
commit e9d81fb0f2
  1. 31
      src/core/ext/transport/cronet/transport/cronet_transport.cc
  2. 26
      test/cpp/ios/CronetTests/CppCronetEnd2EndTests.mm

@ -40,6 +40,7 @@
#include "src/core/lib/surface/validate_metadata.h" #include "src/core/lib/surface/validate_metadata.h"
#include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/timeout_encoding.h"
#include "src/core/lib/transport/transport_impl.h" #include "src/core/lib/transport/transport_impl.h"
#include "third_party/objective_c/Cronet/bidirectional_stream_c.h" #include "third_party/objective_c/Cronet/bidirectional_stream_c.h"
@ -718,16 +719,20 @@ static void create_grpc_frame(grpc_slice_buffer* write_slice_buffer,
Convert metadata in a format that Cronet can consume Convert metadata in a format that Cronet can consume
*/ */
static void convert_metadata_to_cronet_headers( static void convert_metadata_to_cronet_headers(
grpc_linked_mdelem* head, const char* host, char** pp_url, grpc_metadata_batch* metadata, const char* host, char** pp_url,
bidirectional_stream_header** pp_headers, size_t* p_num_headers, bidirectional_stream_header** pp_headers, size_t* p_num_headers,
const char** method) { const char** method) {
grpc_linked_mdelem* curr = head; grpc_linked_mdelem* curr = metadata->list.head;
/* Walk the linked list and get number of header fields */ /* Walk the linked list and get number of header fields */
size_t num_headers_available = 0; size_t num_headers_available = 0;
while (curr != nullptr) { while (curr != nullptr) {
curr = curr->next; curr = curr->next;
num_headers_available++; num_headers_available++;
} }
grpc_millis deadline = metadata->deadline;
if (deadline != GRPC_MILLIS_INF_FUTURE) {
num_headers_available++;
}
/* Allocate enough memory. It is freed in the on_stream_ready callback /* Allocate enough memory. It is freed in the on_stream_ready callback
*/ */
bidirectional_stream_header* headers = bidirectional_stream_header* headers =
@ -740,7 +745,7 @@ static void convert_metadata_to_cronet_headers(
are not used for cronet. are not used for cronet.
TODO (makdharma): Eliminate need to traverse the LL second time for perf. TODO (makdharma): Eliminate need to traverse the LL second time for perf.
*/ */
curr = head; curr = metadata->list.head;
size_t num_headers = 0; size_t num_headers = 0;
while (num_headers < num_headers_available) { while (num_headers < num_headers_available) {
grpc_mdelem mdelem = curr->md; grpc_mdelem mdelem = curr->md;
@ -788,6 +793,18 @@ static void convert_metadata_to_cronet_headers(
break; break;
} }
} }
if (deadline != GRPC_MILLIS_INF_FUTURE) {
char* key = grpc_slice_to_c_string(GRPC_MDSTR_GRPC_TIMEOUT);
char* value =
static_cast<char*>(gpr_malloc(GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE));
grpc_http2_encode_timeout(deadline - grpc_core::ExecCtx::Get()->Now(),
value);
headers[num_headers].key = key;
headers[num_headers].value = value;
num_headers++;
}
*p_num_headers = num_headers; *p_num_headers = num_headers;
} }
@ -1028,10 +1045,10 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) {
char* url = nullptr; char* url = nullptr;
const char* method = "POST"; const char* method = "POST";
s->header_array.headers = nullptr; s->header_array.headers = nullptr;
convert_metadata_to_cronet_headers(stream_op->payload->send_initial_metadata convert_metadata_to_cronet_headers(
.send_initial_metadata->list.head, stream_op->payload->send_initial_metadata.send_initial_metadata,
t->host, &url, &s->header_array.headers, t->host, &url, &s->header_array.headers, &s->header_array.count,
&s->header_array.count, &method); &method);
s->header_array.capacity = s->header_array.count; s->header_array.capacity = s->header_array.count;
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url); CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url);
bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, false); bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, false);

@ -536,6 +536,32 @@ using grpc::ClientContext;
XCTAssertEqual(response.param().request_deadline(), gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec); XCTAssertEqual(response.param().request_deadline(), gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec);
} }
- (void)testEchoDeadline {
auto stub = [self getStub];
EchoRequest request;
EchoResponse response;
request.set_message("Hello");
request.mutable_param()->set_echo_deadline(true);
ClientContext context;
std::chrono::system_clock::time_point deadline =
std::chrono::system_clock::now() + std::chrono::seconds(100);
context.set_deadline(deadline);
Status s = stub->Echo(&context, request, &response);
XCTAssertEqual(response.message(), request.message());
XCTAssertTrue(s.ok());
gpr_timespec sent_deadline;
grpc::Timepoint2Timespec(deadline, &sent_deadline);
// We want to allow some reasonable error given:
// - request_deadline() only has 1sec resolution so the best we can do is +-1
// - if sent_deadline.tv_nsec is very close to the next second's boundary we
// can end up being off by 2 in one direction.
XCTAssertLessThanOrEqual(response.param().request_deadline() - sent_deadline.tv_sec, 2);
XCTAssertGreaterThanOrEqual(response.param().request_deadline() - sent_deadline.tv_sec, -1);
NSLog(@"request deadline: %d sent_deadline: %d", response.param().request_deadline(),
sent_deadline.tv_sec);
}
- (void)testPeer { - (void)testPeer {
auto stub = [self getStub]; auto stub = [self getStub];
EchoRequest request; EchoRequest request;

Loading…
Cancel
Save