From 1c54cb2c861e4f221892c718bf01ec54807d0b51 Mon Sep 17 00:00:00 2001 From: klzgrad Date: Mon, 2 May 2022 17:09:36 +0800 Subject: [PATCH] Add Cronet bidirectional example --- .github/workflows/build.yml | 5 + src/BUILD.gn | 1 + src/build.sh | 3 +- src/components/cronet/BUILD.gn | 93 +--------- src/components/cronet/native/BUILD.gn | 26 --- .../cronet/native/sample/bidi_example.cc | 165 ++++++++++++++++++ src/components/grpc_support/BUILD.gn | 29 --- src/components/prefs/BUILD.gn | 54 +----- src/net/spdy/spdy_http_utils.cc | 4 + 9 files changed, 179 insertions(+), 201 deletions(-) create mode 100644 src/components/cronet/native/sample/bidi_example.cc diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 27e89480d9..5b98a8ba20 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -134,6 +134,7 @@ jobs: - run: ccache -s - run: ../tests/basic.sh out/Release/naive - run: mkdir ${{ env.BUNDLE }} && cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} + - run: cp out/Release/libcronet.* components/cronet/native/generated/cronet.idl_c.h components/cronet/native/include/*.h components/grpc_support/include/*.h components/cronet/native/sample/bidi_example.cc ${{ env.BUNDLE }} - run: tar cJf ../${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} - uses: actions/upload-release-asset@v1 if: ${{ github.event_name == 'release' }} @@ -204,6 +205,7 @@ jobs: # qemu-user segfaults with x64 or x86 android builds here. if: ${{ matrix.arch != 'x64' && matrix.arch != 'x86' }} - run: mkdir ${{ env.BUNDLE }} && cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} + - run: cp out/Release/libcronet.* components/cronet/native/generated/cronet.idl_c.h components/cronet/native/include/*.h components/grpc_support/include/*.h components/cronet/native/sample/bidi_example.cc ${{ env.BUNDLE }} - run: tar cJf ../${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} - uses: actions/upload-release-asset@v1 if: ${{ github.event_name == 'release' }} @@ -269,6 +271,7 @@ jobs: # No real or emulated environment is available to test this. if: ${{ matrix.arch != 'arm64' }} - run: mkdir ${{ env.BUNDLE }} && cp out/Release/naive.exe config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} + - run: cp out/Release/libcronet.* components/cronet/native/generated/cronet.idl_c.h components/cronet/native/include/*.h components/grpc_support/include/*.h components/cronet/native/sample/bidi_example.cc ${{ env.BUNDLE }} - run: 7z a ../${{ env.BUNDLE }}.zip ${{ env.BUNDLE }} - uses: actions/upload-release-asset@v1 if: ${{ github.event_name == 'release' }} @@ -323,6 +326,7 @@ jobs: # No real or emulated environment is available to test this. if: ${{ matrix.arch != 'arm64' }} - run: mkdir ${{ env.BUNDLE }} && cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} + - run: cp out/Release/libcronet.* components/cronet/native/generated/cronet.idl_c.h components/cronet/native/include/*.h components/grpc_support/include/*.h components/cronet/native/sample/bidi_example.cc ${{ env.BUNDLE }} - run: tar cJf ../${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} - uses: actions/upload-release-asset@v1 if: ${{ github.event_name == 'release' }} @@ -476,6 +480,7 @@ jobs: - run: ccache -s - run: ../tests/basic.sh out/Release/naive - run: mkdir ${{ env.BUNDLE }} && cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }} + - run: cp out/Release/libcronet.* components/cronet/native/generated/cronet.idl_c.h components/cronet/native/include/*.h components/grpc_support/include/*.h components/cronet/native/sample/bidi_example.cc ${{ env.BUNDLE }} - run: tar cJf ../${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }} - uses: actions/upload-release-asset@v1 if: ${{ github.event_name == 'release' }} diff --git a/src/BUILD.gn b/src/BUILD.gn index 250ac16619..100ced007d 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -53,6 +53,7 @@ group("gn_all") { deps = [ ":gn_visibility", "//net", + "//components/cronet", ] } diff --git a/src/build.sh b/src/build.sh index e79c38d28d..2515d4ab77 100755 --- a/src/build.sh +++ b/src/build.sh @@ -13,6 +13,7 @@ if [ "$1" = debug ]; then else out=out/Release flags=" + use_thin_lto=false is_cfi=false is_official_build=true exclude_unwind_tables=true enable_resource_allowlist_generation=false @@ -68,4 +69,4 @@ export DEPOT_TOOLS_WIN_TOOLCHAIN=0 ./gn/out/gn gen "$out" --args="$flags $EXTRA_FLAGS" --script-executable=$PYTHON -ninja -C "$out" naive +ninja -C "$out" naive cronet diff --git a/src/components/cronet/BUILD.gn b/src/components/cronet/BUILD.gn index 2db3d1fd4a..33d59cb28e 100644 --- a/src/components/cronet/BUILD.gn +++ b/src/components/cronet/BUILD.gn @@ -9,11 +9,10 @@ import("//build/util/process_version.gni") import("//build/util/version.gni") import("//components/cronet/native/include/headers.gni") import("//components/grpc_support/include/headers.gni") -import("//testing/test.gni") declare_args() { # If set to true, this will remove histogram manager to reduce binary size. - disable_histogram_support = is_mac || is_win + disable_histogram_support = true } # Disable histogram support is not allowed on Android. @@ -59,7 +58,6 @@ source_set("cronet_common") { "//base", "//components/prefs:prefs", "//net", - "//third_party/metrics_proto", ] if (!disable_histogram_support) { @@ -75,23 +73,6 @@ source_set("metrics_util") { deps = [ "//base" ] } -# Unit tests for Cronet common implementation. -source_set("cronet_common_unittests") { - testonly = true - - deps = [ - ":cronet_common", - "//components/prefs:test_support", - "//net:test_support", - ] - - sources = [ - "host_cache_persistence_manager_unittest.cc", - "stale_host_resolver_unittest.cc", - "url_request_context_config_unittest.cc", - ] -} - # For platforms on which the native Cronet library is used, build the library, # a cronet_tests binary that exercises it, and a unit-tests binary. # Android and iOS have their own platform-specific rules to build Cronet. @@ -138,50 +119,6 @@ if (is_android) { } } - test("cronet_tests") { - deps = [ - ":cronet_common", - "//base", - "//base/test:test_support", - "//components/cronet/native:cronet_native_impl", - "//components/cronet/native/test:cronet_native_tests", - "//net", - ] - - sources = [ - "cronet_global_state_stubs.cc", - "run_all_unittests.cc", - ] - - defines = [ "CRONET_TESTS_IMPLEMENTATION" ] - - if ((is_linux || is_chromeos) && !is_component_build) { - public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } - - if (is_fuchsia) { - use_cfv2 = false - additional_manifest_fragments = - [ "//build/config/fuchsia/test/network_capabilities.test-cmx" ] - } - } - - test("cronet_unittests") { - deps = [ - ":cronet_common", - ":cronet_common_unittests", - "//base", - "//base/test:test_support", - "//components/cronet/native:cronet_native_unittests", - "//net", - ] - - sources = [ - "cronet_global_state_stubs.cc", - "run_all_unittests.cc", - ] - } - _package_dir = "$root_out_dir/cronet" # Generate LICENSE file by recursively joining all dependent licenses. @@ -227,30 +164,10 @@ if (is_android) { ] } - executable("cronet_native_perf_test") { - testonly = true - sources = [ - "native/perftest/main.cc", - "native/perftest/perf_test.cc", - ] - deps = [ - "//base", - "//components/cronet", - "//components/cronet/native:cronet_native_headers", - "//components/cronet/native/test:cronet_native_tests", - "//components/cronet/native/test:cronet_native_testutil", - "//net:test_support", - ] - } - executable("cronet_sample") { testonly = true sources = [ "native/sample/main.cc", - "native/sample/sample_executor.cc", - "native/sample/sample_executor.h", - "native/sample/sample_url_request_callback.cc", - "native/sample/sample_url_request_callback.h", ] deps = [ "//components/cronet", @@ -260,12 +177,4 @@ if (is_android) { public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] } } - - test("cronet_sample_test") { - sources = [ "native/sample/test/sample_test.cc" ] - deps = [ - ":cronet_sample", - "//testing/gtest:gtest", - ] - } } diff --git a/src/components/cronet/native/BUILD.gn b/src/components/cronet/native/BUILD.gn index 6ee1271cf3..c3bc307f27 100644 --- a/src/components/cronet/native/BUILD.gn +++ b/src/components/cronet/native/BUILD.gn @@ -4,7 +4,6 @@ import("//components/cronet/native/include/headers.gni") import("//components/grpc_support/include/headers.gni") -import("//testing/test.gni") config("cronet_native_include_config") { include_dirs = [ @@ -71,28 +70,3 @@ source_set("cronet_native_impl") { ] } -# Unit tests for Cronet native API. Depends on cronet_native_impl to test -# implementation details. -source_set("cronet_native_unittests") { - testonly = true - - deps = [ - ":cronet_native_impl", - "//base/test:test_support", - "//components/cronet/native/test:cronet_native_testutil", - "//net:test_support", - "//testing/gtest", - ] - - configs += [ ":cronet_native_include_config" ] - - sources = [ - "engine_unittest.cc", - "native_metrics_util_test.cc", - "runnables_unittest.cc", - - # Generated from cronet.idl. - "generated/cronet.idl_impl_interface_unittest.cc", - "generated/cronet.idl_impl_struct_unittest.cc", - ] -} diff --git a/src/components/cronet/native/sample/bidi_example.cc b/src/components/cronet/native/sample/bidi_example.cc new file mode 100644 index 0000000000..5f96646ab2 --- /dev/null +++ b/src/components/cronet/native/sample/bidi_example.cc @@ -0,0 +1,165 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ninja -C out/Release cronet +// g++ components/cronet/native/sample/bidi_example.cc -I +// components/cronet/native/generated -I components/cronet/native/include -I +// components/grpc_support/include/ out/Release/libcronet.100.0.4896.60.so +// LD_LIBRARY_PATH=out/Release ./a.out +#include +#include +#include +#include + +#include "bidirectional_stream_c.h" +#include "cronet_c.h" + +class BidirectionalStreamCallback { + public: + bidirectional_stream* stream = nullptr; + std::string write_data; + std::string read_buffer; + std::atomic done = false; + + bidirectional_stream_callback* callback() const { return &s_callback; } + + private: + static BidirectionalStreamCallback* FromStream(bidirectional_stream* stream) { + return reinterpret_cast(stream->annotation); + } + + // C callbacks. + static void on_stream_ready_callback(bidirectional_stream* stream) { + std::cout << "on_stream_ready_callback" << std::endl; + BidirectionalStreamCallback* self = FromStream(stream); + bidirectional_stream_write(stream, self->write_data.data(), + self->write_data.size(), true); + bidirectional_stream_flush(stream); + } + + static void on_response_headers_received_callback( + bidirectional_stream* stream, + const bidirectional_stream_header_array* headers, + const char* negotiated_protocol) { + std::cout << "on_response_headers_received_callback negotiated_protocol=" + << negotiated_protocol << "\n"; + BidirectionalStreamCallback* self = FromStream(stream); + for (size_t i = 0; i < headers->count; ++i) { + if (headers->headers[i].key[0] == '\0') + continue; + std::cout << headers->headers[i].key << ": " << headers->headers[i].value + << std::endl; + } + self->read_buffer.resize(32768); + bidirectional_stream_read(stream, self->read_buffer.data(), + self->read_buffer.size()); + } + + static void on_read_completed_callback(bidirectional_stream* stream, + char* data, + int count) { + std::cout << "on_read_completed_callback " << count << "\n"; + BidirectionalStreamCallback* self = FromStream(stream); + if (count == 0) + return; + std::cout.write(data, count); + std::cout << "\n"; + bidirectional_stream_read(stream, self->read_buffer.data(), + self->read_buffer.size()); + } + + static void on_write_completed_callback(bidirectional_stream* stream, + const char* data) { + std::cout << "on_write_completed_callback\n"; + } + + static void on_response_trailers_received_callback( + bidirectional_stream* stream, + const bidirectional_stream_header_array* trailers) { + std::cout << "on_response_trailers_received_callback\n"; + for (size_t i = 0; i < trailers->count; ++i) { + std::cout << trailers->headers[i].key << ": " + << trailers->headers[i].value << std::endl; + } + } + + static void on_succeded_callback(bidirectional_stream* stream) { + std::cout << "on_succeded_callback\n"; + BidirectionalStreamCallback* self = FromStream(stream); + self->done = true; + } + + static void on_failed_callback(bidirectional_stream* stream, int net_error) { + std::cout << "on_failed_callback " << net_error << "\n"; + BidirectionalStreamCallback* self = FromStream(stream); + self->done = true; + } + + static void on_canceled_callback(bidirectional_stream* stream) { + std::cout << "on_canceled_callback\n"; + BidirectionalStreamCallback* self = FromStream(stream); + self->done = true; + } + + static bidirectional_stream_callback s_callback; +}; + +bidirectional_stream_callback BidirectionalStreamCallback::s_callback = { + on_stream_ready_callback, + on_response_headers_received_callback, + on_read_completed_callback, + on_write_completed_callback, + on_response_trailers_received_callback, + on_succeded_callback, + on_failed_callback, + on_canceled_callback, +}; + +Cronet_EnginePtr CreateCronetEngine() { + Cronet_EnginePtr cronet_engine = Cronet_Engine_Create(); + Cronet_EngineParamsPtr engine_params = Cronet_EngineParams_Create(); + Cronet_EngineParams_user_agent_set(engine_params, "CronetSample/1"); + Cronet_EngineParams_experimental_options_set(engine_params, R"( + {"ssl_key_log_file": "/tmp/keys"} +)"); + + Cronet_Engine_StartWithParams(cronet_engine, engine_params); + Cronet_EngineParams_Destroy(engine_params); + return cronet_engine; +} + +int main(int argc, const char* argv[]) { + if (argc != 3) { + std::cout << "Usage: " << argv[0] + << " https://my-caddy-forwardproxy.com \"Basic $(printf " + "user:pass | base64)\"\n"; + return 1; + } + const char* proxy_server = argv[1]; + const char* password_base64 = argv[2]; + Cronet_EnginePtr cronet_engine = CreateCronetEngine(); + stream_engine* cronet_stream_engine = + Cronet_Engine_GetStreamEngine(cronet_engine); + + BidirectionalStreamCallback stream_callback; + stream_callback.write_data = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"; + stream_callback.stream = bidirectional_stream_create( + cronet_stream_engine, &stream_callback, stream_callback.callback()); + bidirectional_stream_header headers[2] = { + {"proxy-authorization", password_base64}, + {"real-authority", "example.com:80"}, + }; + bidirectional_stream_header_array header_array = {2, 2, headers}; + bidirectional_stream_start(stream_callback.stream, proxy_server, 0, "CONNECT", + &header_array, false); + std::cout << "bidirectional_stream_start" << std::endl; + while (!stream_callback.done) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + bidirectional_stream_destroy(stream_callback.stream); + + Cronet_Engine_Shutdown(cronet_engine); + Cronet_Engine_Destroy(cronet_engine); + return 0; +} diff --git a/src/components/grpc_support/BUILD.gn b/src/components/grpc_support/BUILD.gn index 133aa30159..89fd8fde4e 100644 --- a/src/components/grpc_support/BUILD.gn +++ b/src/components/grpc_support/BUILD.gn @@ -18,32 +18,3 @@ source_set("grpc_support") { ] } -# Depends on ":grpc_support" implementation. -source_set("bidirectional_stream_unittest") { - testonly = true - sources = [ "bidirectional_stream_unittest.cc" ] - - deps = [ - ":grpc_support", - "//base", - "//net", - "//net:test_support", - ] - - public_deps = [ "//components/grpc_support/test:get_stream_engine_header" ] -} - -# Depends on ":headers" to avoid ":grpc_support" implementation. -source_set("bidirectional_stream_test") { - testonly = true - sources = [ "bidirectional_stream_unittest.cc" ] - - deps = [ - ":headers", - "//base", - "//net", - "//net:test_support", - ] - - public_deps = [ "//components/grpc_support/test:get_stream_engine_header" ] -} diff --git a/src/components/prefs/BUILD.gn b/src/components/prefs/BUILD.gn index c1828d1027..21b5883bfd 100644 --- a/src/components/prefs/BUILD.gn +++ b/src/components/prefs/BUILD.gn @@ -65,56 +65,4 @@ component("prefs") { ] deps += [ "android:jni_headers" ] } -} - -static_library("test_support") { - testonly = true - sources = [ - "mock_pref_change_callback.cc", - "mock_pref_change_callback.h", - "pref_store_observer_mock.cc", - "pref_store_observer_mock.h", - "pref_test_utils.cc", - "pref_test_utils.h", - "testing_pref_service.cc", - "testing_pref_service.h", - "testing_pref_store.cc", - "testing_pref_store.h", - ] - - public_deps = [ ":prefs" ] - deps = [ - "//base", - "//base/test:test_support", - "//testing/gmock", - "//testing/gtest", - ] -} - -source_set("unit_tests") { - testonly = true - sources = [ - "default_pref_store_unittest.cc", - "in_memory_pref_store_unittest.cc", - "json_pref_store_unittest.cc", - "overlay_user_pref_store_unittest.cc", - "persistent_pref_store_unittest.cc", - "persistent_pref_store_unittest.h", - "pref_change_registrar_unittest.cc", - "pref_member_unittest.cc", - "pref_notifier_impl_unittest.cc", - "pref_service_unittest.cc", - "pref_value_map_unittest.cc", - "pref_value_store_unittest.cc", - "scoped_user_pref_update_unittest.cc", - "segregated_pref_store_unittest.cc", - ] - - deps = [ - ":test_support", - "//base", - "//base/test:test_support", - "//testing/gmock", - "//testing/gtest", - ] -} +} \ No newline at end of file diff --git a/src/net/spdy/spdy_http_utils.cc b/src/net/spdy/spdy_http_utils.cc index 3592f9ec1b..e942278106 100644 --- a/src/net/spdy/spdy_http_utils.cc +++ b/src/net/spdy/spdy_http_utils.cc @@ -107,6 +107,10 @@ void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, HttpRequestHeaders::Iterator it(request_headers); while (it.GetNext()) { std::string name = base::ToLowerASCII(it.name()); + if (info.method == "CONNECT" && name == "_real_authority") { + (*headers)[spdy::kHttp2AuthorityHeader] = it.value(); + continue; + } if (name.empty() || name[0] == ':' || name == "connection" || name == "proxy-connection" || name == "transfer-encoding" || name == "host") {