Add `num_ohttp_chunks` flag and remove `chunked` flag. If `num_ohttp_chunks` is not set or is set to 0, the logic will use standard non-chunked OHTTP. If it is more than 0, then it will use chunked OHTTP and attempt to split the serialized BHTTP request data (regardless of it being known-length or indeterminate-length) by `num_ohttp_chunks`. PiperOrigin-RevId: 897766842
diff --git a/quiche/quic/masque/masque_ohttp_client.cc b/quiche/quic/masque/masque_ohttp_client.cc index 6e8d5d2..49f2573 100644 --- a/quiche/quic/masque/masque_ohttp_client.cc +++ b/quiche/quic/masque/masque_ohttp_client.cc
@@ -425,7 +425,7 @@ std::string encoded_data; int num_bhttp_chunks = per_request_config.num_bhttp_chunks(); if (num_bhttp_chunks < 0) { - num_bhttp_chunks = (per_request_config.use_chunked_ohttp() ? 1 : 0); + num_bhttp_chunks = (per_request_config.num_ohttp_chunks() > 0 ? 1 : 0); } if (num_bhttp_chunks > 0) { BinaryHttpRequest::IndeterminateLengthEncoder encoder; @@ -466,23 +466,24 @@ binary_request.set_body(post_data); QUICHE_ASSIGN_OR_RETURN(encoded_data, binary_request.Serialize()); } - if (pending_request.per_request_config.use_chunked_ohttp()) { + int num_ohttp_chunks = pending_request.per_request_config.num_ohttp_chunks(); + if (num_ohttp_chunks > 0) { pending_request.chunk_handler = std::make_unique<ChunkHandler>(); QUICHE_ASSIGN_OR_RETURN( ChunkedObliviousHttpClient chunked_client, ChunkedObliviousHttpClient::Create( ohttp_client_->GetPublicKey(), ohttp_client_->GetKeyConfig(), pending_request.chunk_handler.get())); - // Intentionally split the data into two chunks to test encryption chunking. - QUICHE_ASSIGN_OR_RETURN(encrypted_data, - chunked_client.EncryptRequestChunk( - absl::string_view(encoded_data).substr(0, 1), - /*is_final_chunk=*/false)); - QUICHE_ASSIGN_OR_RETURN(std::string encrypted_data2, - chunked_client.EncryptRequestChunk( - absl::string_view(encoded_data).substr(1), - /*is_final_chunk=*/true)); - encrypted_data += encrypted_data2; + QUICHE_ASSIGN_OR_RETURN(std::vector<absl::string_view> ohttp_chunks, + SplitIntoChunks(encoded_data, num_ohttp_chunks)); + + for (size_t i = 0; i < ohttp_chunks.size(); i++) { + bool is_final_chunk = (i == ohttp_chunks.size() - 1); + QUICHE_ASSIGN_OR_RETURN( + std::string ohttp_chunk, + chunked_client.EncryptRequestChunk(ohttp_chunks[i], is_final_chunk)); + encrypted_data += ohttp_chunk; + } pending_request.chunk_handler->SetChunkedClient(std::move(chunked_client)); } else { @@ -498,9 +499,7 @@ request.headers[":authority"] = relay_url_.HostPort(); request.headers[":path"] = relay_url_.PathParamsQuery(); request.headers["content-type"] = - pending_request.per_request_config.use_chunked_ohttp() - ? "message/ohttp-chunked-req" - : "message/ohttp-req"; + num_ohttp_chunks > 0 ? "message/ohttp-chunked-req" : "message/ohttp-req"; for (const std::pair<std::string, std::string>& header : per_request_config.outer_headers()) { request.headers[header.first] = header.second; @@ -598,9 +597,10 @@ return absl::InvalidArgumentError( absl::StrCat("Bad gateway status code: ", gateway_status_code)); } - std::string content_type = it->second.per_request_config.use_chunked_ohttp() - ? "message/ohttp-chunked-res" - : "message/ohttp-res"; + std::string content_type = + it->second.per_request_config.num_ohttp_chunks() > 0 + ? "message/ohttp-chunked-res" + : "message/ohttp-res"; std::optional<uint16_t> expected_gateway_status_code = it->second.per_request_config.expected_gateway_status_code(); absl::Status status = CheckStatusAndContentType(*response, content_type, @@ -623,7 +623,7 @@ std::optional<Message> encapsulated_response; QUICHE_VLOG(2) << "Received encrypted response body: " << absl::BytesToHexString(response->body); - if (it->second.per_request_config.use_chunked_ohttp()) { + if (it->second.per_request_config.num_ohttp_chunks() > 0) { QUICHE_ASSIGN_OR_RETURN( encapsulated_response, it->second.chunk_handler->DecryptFullResponse(response->body));
diff --git a/quiche/quic/masque/masque_ohttp_client.h b/quiche/quic/masque/masque_ohttp_client.h index 8a5c02b..32fbdca 100644 --- a/quiche/quic/masque/masque_ohttp_client.h +++ b/quiche/quic/masque/masque_ohttp_client.h
@@ -51,10 +51,8 @@ absl::Status AddOuterHeaders( const std::vector<std::string>& outer_headers); absl::Status AddPrivateToken(const std::string& private_token); - void SetUseChunkedOhttp(bool use_chunked_ohttp) { - use_chunked_ohttp_ = use_chunked_ohttp; - } void SetNumBhttpChunks(int num_chunks) { num_bhttp_chunks_ = num_chunks; } + void SetNumOhttpChunks(int num_chunks) { num_ohttp_chunks_ = num_chunks; } void SetExpectedGatewayError(const std::string& expected_gateway_error) { expected_gateway_error_ = expected_gateway_error; } @@ -80,8 +78,8 @@ const { return outer_headers_; } - bool use_chunked_ohttp() const { return use_chunked_ohttp_; } int num_bhttp_chunks() const { return num_bhttp_chunks_; } + int num_ohttp_chunks() const { return num_ohttp_chunks_; } std::optional<std::string> expected_gateway_error() const { return expected_gateway_error_; } @@ -101,7 +99,7 @@ std::optional<std::string> method_; std::vector<std::pair<std::string, std::string>> headers_; std::vector<std::pair<std::string, std::string>> outer_headers_; - bool use_chunked_ohttp_ = false; + int num_ohttp_chunks_ = 0; int num_bhttp_chunks_ = -1; std::optional<std::string> expected_gateway_error_; std::optional<uint16_t> expected_gateway_status_code_;
diff --git a/quiche/quic/masque/masque_ohttp_client_bin.cc b/quiche/quic/masque/masque_ohttp_client_bin.cc index fab77ab..071cc51 100644 --- a/quiche/quic/masque/masque_ohttp_client_bin.cc +++ b/quiche/quic/masque/masque_ohttp_client_bin.cc
@@ -29,9 +29,6 @@ bool, use_mtls_for_key_fetch, false, "If true, use mTLS when fetching the OHTTP/HPKE keys."); -DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, chunked, false, - "If true, use chunked OHTTP."); - DEFINE_QUICHE_COMMAND_LINE_FLAG(int, address_family, 0, "IP address family to use. Must be 0, 4 or 6. " "Defaults to 0 which means any."); @@ -60,10 +57,16 @@ DEFINE_QUICHE_COMMAND_LINE_FLAG( int, num_bhttp_chunks, -1, "Number of indeterminate-length BHTTP chunks to split post data into. If " - "not set or if set to -1, it will match the chunked flag mode. If set to " + "not set or if set to -1, it will match the chunked mode (see " + "--num_ohttp_chunks). If set to " "0, the client will use known-length BHTTP."); DEFINE_QUICHE_COMMAND_LINE_FLAG( + int, num_ohttp_chunks, 0, + "Number of OHTTP chunks to split serialized BHTTP request into. If not set " + "or if set to 0, the client will use standard non-chunked OHTTP."); + +DEFINE_QUICHE_COMMAND_LINE_FLAG( std::vector<std::string>, header, {}, "Adds a header field to the encapsulated binary request. Separate the " "header name and value with a colon. Can be specified multiple times."); @@ -120,8 +123,6 @@ quiche::GetQuicheCommandLineFlag(FLAGS_disable_certificate_verification); const bool use_mtls_for_key_fetch = quiche::GetQuicheCommandLineFlag(FLAGS_use_mtls_for_key_fetch); - const bool use_chunked_ohttp = - quiche::GetQuicheCommandLineFlag(FLAGS_chunked); const std::string client_cert_file = quiche::GetQuicheCommandLineFlag(FLAGS_client_cert_file); const std::string client_cert_key_file = @@ -154,6 +155,8 @@ } std::optional<std::string> method = quiche::GetQuicheCommandLineFlag(FLAGS_method); + const int num_ohttp_chunks = + quiche::GetQuicheCommandLineFlag(FLAGS_num_ohttp_chunks); const int num_bhttp_chunks = quiche::GetQuicheCommandLineFlag(FLAGS_num_bhttp_chunks); std::vector<std::string> headers = @@ -224,7 +227,7 @@ QUICHE_RETURN_IF_ERROR( per_request_config.AddPrivateToken(generated_private_token)); } - per_request_config.SetUseChunkedOhttp(use_chunked_ohttp); + per_request_config.SetNumOhttpChunks(num_ohttp_chunks); per_request_config.SetNumBhttpChunks(num_bhttp_chunks); if (expect_gateway_error.has_value()) { per_request_config.SetExpectedGatewayError(*expect_gateway_error);